在下面的代码中,我只是想看看我是否能够从每个线程中将元素插入到数组中。它按预期工作。但后来我想知道,在什么情况下可能存在竞争条件。我真的需要挥发性或信号量吗?我尝试删除信号量和易失性关键字,仍然有效。我想在这里诱导并看到一个竞争条件场景。在同一行上,我可以从每个线程创建一个节点并将所有节点放入链表吗?这些都是想象中的场景.. !!
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include "small_appl.h"
void * thread_func(void * arg);
int itr=0;
volatile int idx=0; //array index variable
sem_t sem1;
int arr_th[5]; //array where each thread will insert an element
int func_pointed(int a,int num_t)
{
pthread_t arr_thr[num_t];
int iter;
//create threads
for(iter=0;iter<num_t;iter++)
{
pthread_create(&arr_thr[iter],NULL,thread_func,(void *)a);
}
for (iter=0;iter<num_t;iter++)
{
pthread_join(arr_thr[iter],NULL);
}
}
int main(void)
{
int ip1=5,ip2=10,rev;
rev=sem_init(&sem1,0,0);
s_type dev_s={
.f_ptr=func_pointed,
.str="Diwakar",
.val=5
};
//initialize semaphore to 1
sem_post(&sem1);
func_aux(ip1,dev_s);
for(rev=0;rev<5;rev++)
{
printf("array : %d ",arr_th[rev]);
}
}
void * thread_func(void * arg)
{
sem_wait(&sem1);
printf("Got sema\n");
arr_th[idx]=itr;
idx++; itr++;
printf("Releasing sema\n");
sem_post(&sem1);
sleep(5);
}
答案 0 :(得分:1)
创建或模拟线程覆盖另一个线程完成的工作的情况,然后删除信号量并策略性地放置睡眠,如下所示:
void * thread_func(void * arg)
{
//sem_wait(&sem1);
//printf("Got sema\n");
arr_th[idx]=itr;
// print arr_th[idx]
sleep(5); <<== gives the threads more of a chance to wipe-out each other
// print arr_th[idx]
idx++; itr++;
//printf("Releasing sema\n");
//sem_post(&sem1);
sleep(5);
}
您可以添加一些明确突出显示问题的printf
语句。
volatile
告诉编译器不要删除未使用或至少看似未使用的变量。
您可以从多个线程更新链接列表,但必须序列化更新列表中链接(下一个和/或上一个)的代码的关键部分。
在Windows XP及更高版本中,CRT是线程安全的,因此每个线程都可以发出malloc()
,printf
等,而无需序列化这些调用的线程。
答案 1 :(得分:1)
volatile指示编译器可以随时更改变量。这意味着对变量的每次引用都必须从内存中读取(而不是在寄存器中重用该值的副本)。
volatile int i;
if(i==0) return
if(i==1) ...
如果volatile
关键字不存在,编译器可能会将该变量读取到寄存器一次,并将其检查为0和1。
如果在主程序中等待idx变量为这样的特定值,则应将其设为volatile
。
while(idx==10);
Volatile不会使其线程安全,这是一个不同的问题。事实上,因为你保护了那部分代码,你不希望idx从一个读取更改为下一个读取,所以你不需要volatile。
如果你想产生竞争条件(检测被分割的代码部分),我建议设置2个值,你可以在2个单独的指令中递增,并在连续的while循环中执行此操作(不睡觉!如果你睡觉你减少关键部分被分裂的可能性)。在主循环中,不断检查值是否相等(再次,没有睡眠)。如果它们不相等,则两部分代码中的一部分已被拆分。还要看看程序集,以确保编译器没有优化。