0

我编写了以下代码来了解使用 pthread 和互斥锁的事件排序。main函数创建两个与函数func1func2相关联的线程。函数func1检查count的值并有条件地等待func2发出信号。函数func2递增计数,当计数达到 50000 时,它向func1发出信号。然后func1打印当时是(或应该是)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;
}
4

2 回答 2

1

您尚未与生产者 func2() 同步,并告诉它等到消费者 func1() 处理完条件。

没有什么能阻止生产者发出条件信号、重新获取互斥体并再次增加计数器。pthread_cond_signal 并不意味着您的生产者将停止并等待消费者处理。这意味着生产者可能会在您的消费者被安排并唤醒以打印当前数字之前多次增加计数器。

您需要添加另一个条件变量,生产者在将计数器增加到 N 后等待该条件变量,并让消费者在处理计数器时发出信号。

除此之外,您需要处理其他答案提到的虚假唤醒。

于 2013-02-08T23:47:09.130 回答
0

一些实现pthread_cond_wait()会受到虚假唤醒的影响,因此,通常的做法是使用while (cond) { pthread_cond_wait(...); }循环来解决这个问题。

我在这里找到了对问题和原因的一个很好的解释:为什么 pthread_cond_wait 有虚假的唤醒?

于 2013-02-08T23:28:37.830 回答