避免 pthread_cond_wait 和 pthread_cond_signal 时发生死锁

ano*_*ous 2 c++ pthreads

我有一个关于使用 pthread 条件变量的问题。一般用例是这样的

//thread 1:
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
do_something()
pthread_mutex_unlock(&mutex);

//thread 2:
pthread_cond_signal(&cond);  
Run Code Online (Sandbox Code Playgroud)

现在我知道 pthead_cond_wait 将解锁互斥体并进入睡眠状态,唤醒时它将锁定互斥体,然后从调用返回,但如何确保线程 1 处于条件等待状态后来自线程 2 的信号到达线程 1。可能会出现线程 2 先运行然后线程 1 导致唤醒丢失的情况。

如果我再次在线程 2 中使用互斥锁,那么线程 2 也可能会获得锁,它会发出信号,而线程 1 仍在尝试获取锁。这将再次导致唤醒丢失。

如何确保来自条件变量的信号到达等待该信号的线程?

谢谢

caf*_*caf 5

您的“一般用例”不正确。条件变量必须与某个共享状态上的条件(称为谓词)配对。一般例是:

主题 1:

pthread_mutex_lock(&mutex);
while (!condition)
    pthread_cond_wait(&cond, &mutex);
do_something(); /* Requiring 'condition' to be true */
pthread_mutex_unlock(&mutex);
Run Code Online (Sandbox Code Playgroud)

话题2:

pthread_mutex_lock(&mutex);
do_something_else(); /* That sets 'condition' true */
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
Run Code Online (Sandbox Code Playgroud)

...其中condition位于受某些共享状态保护的地方mutex- 例如,condition可能正在检查共享队列是否为非空。

该结构中不可能存在丢失唤醒,因为等待线程在等待之前总是检查条件。如果条件已经为真,则它不会等待 - 并且因为它保存保护条件的互斥锁,所以在检查和等待之间它也不会变为真。

(请注意,这pthread_cond_broadcast()是通常使用的正确函数,并且pthread_cond_signal()是适用于许多情况的优化)。