条件变量的谓词

时间:2014-04-03 10:38:31

标签: c++ multithreading concurrency condition-variable

我是多线程新手。在使用条件变量在C ++ 11中编写多线程代码时,我使用以下构造

while(predicate) {
    cond_var.wait(&lock);
}

但是,我一直在阅读Deitel关于操作系统的第三版书(第6页),其中使用了以下结构

if(predicate) {
    cond_var.wait(&lock);
}

那么,区别是什么?为什么这本书不能使用?不是虚假的问题吗?

2 个答案:

答案 0 :(得分:7)

虚假唤醒始终是一个潜在的问题。例如,请查看以下答案:Do spurious wakeups actually happen?。也许Deitel的代码是一个更大的循环的一部分,可以帮助他们处理虚假的唤醒?或许这只是一个错字。

在任何情况下,从来没有(好的)理由不使用你的构造,事实上wait函数有一个为你做的变体(http://en.cppreference.com/w/cpp/thread/condition_variable/wait)。

template< class Predicate >
void wait( std::unique_lock<std::mutex>& lock, Predicate pred );

相当于:

while (!pred()) {
     wait(lock);
}

答案 1 :(得分:1)

人们似乎只是专门处理虚假唤醒,但有一个更为根本的原因,即whileif将用于监控程序。 即使没有虚假唤醒,我们也必须选择其中一个,因为监视器实现可能会从许多不同的信令规则中进行选择。

以下文章介绍了这些

  

John H. Howard。 1976.在监视器中发出信号。在第二届软件工程国际会议论文集(ICSE&#39; 76)中。 IEEE Computer Society Press,Los Alamitos,CA,USA,47-52。

关键是监视器一次最多只能使用一个进程,并且当监视器内部的另一个进程唤醒(发出信号)等待进程时会发生冲突。问题是:哪个进程可能会在监视器内继续执行?

有许多不同的学科。最初提出的那个是所谓的信号并等待,其中发出信号的过程立即继续(信号器必须等待)。

使用这个学科
if ( predicate) {
  cond_var.wait( &lock);
}
可以使用

表单,因为谓词必须在等待后为真(假设在发出信号时为真)

另一个学科是信号并继续,其中信令过程继续,发信号被放入监视器的入口队列。使用这个学科需要使用

while ( predicate) {
  cond_var.wait( &lock);
}

form,因为谓词进程有机会执行时谓词可能无效,因此必须重新测试条件。