我的程序执行"线程同步"使用pthread_cond_wait
和pthread_cond_signal
。它似乎在20次中失败了一次。
我有一个共享变量count
,它被初始化为0。
一个线程递增count
直到count
为20,然后发出条件变量信号。
代码如下。
void* inc_count(void *parm)
{
int i;
for(i = 0 ; i <25; i ++)// adds count to 25
{
pthread_mutex_lock(&mutex1);
count ++;
printf("Thread %lld , count = %d\n",(long long int)pthread_self(),count);
if(count == 20)
{
pthread_cond_signal(&cond);
printf("Thread %lld sends a signal!\n",(long long int)pthread_self());
}
pthread_mutex_unlock(&mutex1);
}
pthread_exit(NULL);
}
void* watch_count(void *parm)
{
while(count < 20)
{
pthread_mutex_lock(&mutex1);
pthread_cond_wait(&cond,&mutex1);
printf("Thread %lld receives the signal!\n",(long long int)pthread_self());
}
pthread_mutex_unlock(&mutex1);
pthread_exit(NULL);
}
int main()
{
pthread_t pt1,pt2,pt3,pt4;
pthread_mutex_init(&mutex1,NULL);
pthread_mutex_init(&mutex2,NULL);
pthread_cond_init(&cond,NULL);
pthread_create(&pt1,NULL,inc_count,NULL);
pthread_create(&pt2,NULL,watch_count,NULL);
pthread_join(pt1,NULL);
pthread_join(pt2,NULL);
}
从图片中,您可以看到线程pt2没有收到信号,为什么?
答案 0 :(得分:3)
您的watch_count()
功能有问题:
while
循环内并且仅在其外部解锁(可以尝试锁定多次而不解锁)count < 20
要修复它,您需要在循环之前而不是在其中锁定互斥锁:
pthread_mutex_lock(&mutex1);
while(count < 20)
{
pthread_cond_wait(&cond,&mutex1);
printf("Thread %lld receives the signal!\n",(long long int)pthread_self());
}
pthread_mutex_unlock(&mutex1);
这样可以防止您在解锁之前多次锁定互斥锁,并确保count
无法修改,并且无法在{{1}的测试之间发送信号条件和while
(pthread_cond_wait
&#39;更改为inc_count()
并且发送信号必须在while循环之前或count
期间发生)。
即使进行了这些更改,如果pthread_cond_wait()
在count
检查它的时候watch_count()
已经是20,那么等待仍然可能会发生。< / p>
答案 1 :(得分:1)
inc_count
线程首次检查之前,你的watch_count
线程有可能超过20 while
条件。
为什么要使用while循环?当inc_count
发送信号时,您已经知道计数超过20,那么为什么要检查呢?
我的解决方案是进行一些握手,确保watch_count
在 inc_count
开始计数之前进入等待状态。为此,您需要确保按顺序执行以下操作:
inc_count
首先输入其代码,然后等待watch_count
初始化watch_count
输入其代码并发出inc_count
已准备就绪的信号watch_count
等待inc_count
发出信号inc_count
开始计数,并在watch_count
到达20 我通过在启动任一线程之前获取互斥锁来实现此目的,然后依靠第一个线程进入其&#34;准备好等待&#34;在开始第二个线程之前的条件。当第二个线程准备就绪时,它会指示第一个线程继续开始计数,这是我的代码:
void* inc_count(void *parm)
{
// holding this mutex on entry;
pthread_mutex_t* m = parm;
int i;
// wait for the watch_count thread to be ready
pthread_cond_wait(&init_cond, m);
pthread_mutex_unlock(m);
// start counting
for(i = 0 ; i < 10000; i ++)
{
pthread_mutex_lock(&count_mutex);
count++;
printf("Thread %lld , count = %d\n",
(long long int) pthread_self(),
count);
if(count == 20)
{
pthread_cond_signal(&count_cond);
printf("Thread %lld sends a signal!\n",
(long long int)pthread_self());
}
pthread_mutex_unlock(&count_mutex);
}
pthread_exit(NULL);
}
void* watch_count(void *parm)
{
// holding this mutex on entry
pthread_mutex_t* m = parm;
pthread_cond_signal(&init_cond); // tell inc_count that you're ready
pthread_cond_wait(&count_cond,m); // wait for him to get to 20
pthread_mutex_unlock(m);
pthread_mutex_lock(&count_mutex);
printf("Thread %lld receives the signal! count == %d\n",
(long long int)pthread_self(),
count);
pthread_mutex_unlock(&count_mutex);
pthread_exit(NULL);
}
int main()
{
pthread_t pt1,pt2;
pthread_mutex_t init_mutex, count_mutex;
pthread_mutex_init(&init_mutex,NULL);
pthread_mutex_init(&count_mutex,NULL);
pthread_cond_init(&init_cond,NULL);
pthread_cond_init(&count_cond,NULL);
// this mutex is released when inc_count has initialized
pthread_mutex_lock(&init_mutex);
pthread_create(&pt1,NULL,inc_count,(void *) &init_mutex);
// this mutex is released when watch-count has initialized
pthread_mutex_lock(&init_mutex);
pthread_create(&pt2,NULL,watch_count,(void *) &init_mutex);
pthread_join(pt1,NULL);
pthread_join(pt2,NULL);
}