c - 为什么需要围绕 pthread 等待条件的 while 循环?

标签 c multithreading pthreads

我正在学习 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);

最佳答案

你应该将 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>

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

关于c - 为什么需要围绕 pthread 等待条件的 while 循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1136371/

相关文章:

c - 使用 pThreads : Deadlock? 实现线程安全队列

C:使用数组,总是给我错误的输出

c - 当输入长度未知时,如何读取以逗号分隔的数字?

java - Java UDP Server 增加内存

c++ - cmake 中的 pthread 和 -pthread 选项有什么区别?

c++ - C++ 中的多线程示例

c - 将静态库链接到动态库时删除死代码

c - ptrace 更改系统调用编号 arm64

multithreading - Servlet 线程池 vs Servlet 实例池 - 通过 Web 容器

python - gevent和线程之间的效率比较