【问题标题】:Why is a while loop needed around pthread wait conditions?为什么在 pthread 等待条件周围需要一个 while 循环?
【发布时间】:2010-11-11 07:18:20
【问题描述】:

我正在学习 pthread 和等待条件。据我所知,一个典型的等待线程是这样的:

pthread_mutex_lock(&m);
while(!condition)
     pthread_cond_wait(&cond, &m);
// Thread stuff here
pthread_mutex_unlock(&m);

我无法理解的是为什么即使我使用pthread_cond_signal() 来唤醒线程,while(!condition) 行也是必要的。

我可以理解,如果我使用pthread_cond_broadcast(),我需要测试条件,因为我唤醒了所有个等待线程,其中一个线程可以在解锁互斥锁之前再次使条件为假(因此将执行转移到另一个此时不应执行的已唤醒线程)。 但是如果我使用 pthread_cond_signal() 我只唤醒 一个 线程,所以条件必须为真。所以代码可能是这样的:

pthread_mutex_lock(&m);
pthread_cond_wait(&cond, &m);
// Thread stuff here
pthread_mutex_unlock(&m);

我读到了一些关于可能发生的虚假信号的文章。这是(而且只有这个)原因吗?为什么我应该有虚假信号?或者还有什么我不明白的?

我假设信号代码是这样的:

pthread_mutex_lock(&m);
condition = true;
pthread_cond_signal(&cond); // Should wake up *one* thread
pthread_mutex_unlock(&m);

【问题讨论】:

    标签: c multithreading pthreads


    【解决方案1】:

    您应该将 pthread_cond_wait 放在 while 循环中的真正原因不是因为虚假唤醒。即使您的条件变量没有虚假唤醒,您仍然需要循环来捕获常见类型的错误。为什么?考虑一下如果多个线程在相同条件下等待会发生什么:

    Thread 1                         Thread 2           Thread 3
    check condition (fails)
    (in cond_wait) unlock mutex
    (in cond_wait) wait
                                     lock mutex
                                     set condition
                                     signal condvar
                                     unlock mutex
                                                        lock mutex
                                                        check condition (succeeds)
                                                        do stuff
                                                        unset condition
                                                        unlock mutex
    (in cond_wait) wake up
    (in cond_wait) lock mutex
    <thread is awake, but condition
    is unset>
    

    这里的问题是线程必须在等待之前释放互斥锁,这可能会允许另一个线程“窃取”该线程正在等待的任何内容。除非保证只有一个线程可以在该条件下等待,否则在线程唤醒时假设该条件有效是不正确的。

    【讨论】:

    • 完全正确。投票赞成。这应该比接受的答案更受关注。
    【解决方案2】:

    假设您不检查条件。那么通常你无法避免以下坏事的发生(至少,你不能在一行代码中避免):

     Sender                             Receiver
    locks mutex
    sets condition
    signals condvar, but nothing 
      is waiting so has no effect
    releases mutex
                                        locks mutex
                                        waits. Forever.
    

    当然,您的第二个代码示例可以通过这样做来避免这种情况:

    pthread_mutex_lock(&m);
    if (!condition) pthread_cond_wait(&cond, &m);
    // Thread stuff here
    pthread_mutex_unlock(&m);
    

    那么肯定会出现这样的情况,如果最多只有一个接收器,并且如果cond_signal 是唯一可以唤醒它的东西,那么它只会在条件设置时唤醒,因此不需要循环。 nos 涵盖了为什么第二个“如果”不正确。

    【讨论】:

    • 我明白了,所以由于逻辑原因(无休止的等待)需要一个“if”,但由于实现问题(虚假信号)实际上需要一段时间。
    • 是的,当我第一次使用 pthreads 库时,我问了同样的问题。我省略了检查状态变量,我的程序会在等待发生之前发出信号。这是等待/信号功能的全部要点。等待内存状态的某些受互斥锁保护的更改并发出信号。
    猜你喜欢
    • 2011-12-07
    • 1970-01-01
    • 2019-12-29
    • 2021-03-21
    • 2020-10-31
    • 2018-09-22
    • 2023-03-17
    • 2015-07-18
    • 1970-01-01
    相关资源
    最近更新 更多