【问题标题】:Unexpected output in event ordering using pthread conditional wait使用 pthread 条件等待的事件排序中的意外输出
【发布时间】:2013-02-08 23:23:48
【问题描述】:

我编写了以下代码来了解使用 pthread 和互斥锁的事件排序。 ma​​in 函数创建两个线程,它们与函数 func1func2 相关联。 func1 函数检查 count 的值并有条件地等待 func2 发出信号。函数 func2 递增 count,当 count 达到 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;
}

【问题讨论】:

    标签: c pthreads


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 您也可以为第二个同步点使用屏障而不是第二个条件变量。
    【解决方案2】:

    pthread_cond_wait() 的一些实现会遭受虚假唤醒,因此,通常使用 while (cond) { pthread_cond_wait(...); } 循环来解决此问题。

    我在这里找到了对问题和原因的一个很好的解释:Why does pthread_cond_wait have spurious wakeups?

    【讨论】:

    • 谢谢,但同时也给出了相同的结果。
    猜你喜欢
    • 2011-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-29
    • 2018-02-07
    • 2022-01-14
    相关资源
    最近更新 更多