使用pthread条件等待的事件排序中的意外输出

时间:2013-02-08 23:23:49

标签: c pthreads

我编写了以下代码,以便使用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;
}

2 个答案:

答案 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?