我编写了以下代码,以便使用pthreads和mutex了解事件排序。 main 函数创建两个与 func1 和 func2 函数关联的线程。函数 func1 检查计数的值,并有条件地等待 func2 发出信号。函数 func2 增加计数,当计数达到50000时,它会发出 func1 信号。 然后 func1 会打印 count 的值,该值在当时(或应该是)50000。
但在实际输出中,除了50000之外,还会打印其他一些值。我没有任何理由为什么会这样。我认为,当 func2 信号时, func1 从pthread_cond_wait语句之后唤醒并执行,因此它应该只打印50000.请指出我错在哪里应该改变什么来获得正确的输出?
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
pthread_mutex_t evmutex;
pthread_cond_t evcond;
char a;
int count;
int N = 50000;
void *func1()
{
while(1)
{
pthread_mutex_lock(&evmutex);
if(count < N)
{
pthread_cond_wait(&evcond,&evmutex);
printf("%d\n",count);
count = 0;
}
pthread_mutex_unlock(&evmutex);
}
}
void *func2()
{
while(1)
{
pthread_mutex_lock(&evmutex);
count++;
if(count == N)
{
pthread_cond_signal(&evcond);
}
pthread_mutex_unlock(&evmutex);
}
}
int main ()
{
pthread_t ptd1,ptd2;
pthread_mutex_init(&evmutex,NULL);
pthread_cond_init(&evcond,NULL);
count = 0;
pthread_create(&ptd1,NULL,func1,NULL);
pthread_create(&ptd2,NULL,func2,NULL);
pthread_exit(NULL);
pthread_mutex_destroy(&evmutex);
pthread_cond_destroy(&evcond);
return 0;
}
答案 0 :(得分:1)
你没有与生产者func2()同步,并告诉它等到消费者func1()处理了这个条件。
没有什么能阻止生产者发出信号,重新获取互斥锁,然后再次递增计数器。 pthread_cond_signal并不意味着您的生产者将停止并等待消费者处理。 这意味着生产者可能会在您的消费者进行计划之前多次递增计数器,然后醒来打印当前的数字。
你需要添加另一个条件变量,生成器在将计数器递增到N后等待它,并让消费者在处理完计数器时发出信号。
除此之外,您需要处理虚假唤醒,如其他答案所述。
答案 1 :(得分:0)
pthread_cond_wait()
的某些实现受到虚假唤醒的影响,因此,通常使用while (cond) { pthread_cond_wait(...); }
循环来解决此问题。
我在这里找到了问题和原因的一个很好的解释:Why does pthread_cond_wait have spurious wakeups?