pthread_cond_wait和pthread_cond_signal

时间:2015-06-04 07:05:40

标签: 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);  

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

如果我再次在线程2中使用互斥锁,那么也可能发生thread2将获得锁定它将发出信号并且thread1仍在尝试获取锁定。这将再次导致失去唤醒。

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

由于

2 个答案:

答案 0 :(得分:3)

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

主题1:

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

主题2:

pthread_mutex_lock(&mutex);
do_something_else(); /* That sets 'condition' true */
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);

... condition位于mutex保护的某个共享状态之上 - 例如,condition可能正在检查共享队列是否为空。

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

(请注意,pthread_cond_broadcast()是一般使用的正确函数,pthread_cond_signal()是一种适用于许多情况的优化。)

答案 1 :(得分:0)

完全基于您的设计。 您可以使用bool变量(例如isSignalled)来同步两者。如下所示(请将其作为一个想法)

//thread 1:
pthread_mutex_lock(&mutex);
if(isSignalled == 0){
    pthread_cond_wait(&cond, &mutex);
}
isSignalled = 0;
do_something()
pthread_mutex_unlock(&mutex);

//thread 2:
pthread_mutex_lock(&mutex);
isSignalled = 1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);