我是多线程新手。在使用条件变量在C ++ 11中编写多线程代码时,我使用以下构造
while(predicate) {
cond_var.wait(&lock);
}
但是,我一直在阅读Deitel关于操作系统的第三版书(第6页),其中使用了以下结构
if(predicate) {
cond_var.wait(&lock);
}
那么,区别是什么?为什么这本书不能使用?不是虚假的问题吗?
答案 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)
人们似乎只是专门处理虚假唤醒,但有一个更为根本的原因,即while
或if
将用于监控程序。
即使没有虚假唤醒,我们也必须选择其中一个,因为监视器实现可能会从许多不同的信令规则中进行选择。
以下文章介绍了这些
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,因为谓词进程有机会执行时谓词可能无效,因此必须重新测试条件。