【问题标题】:predicate for condition variable条件变量的谓词
【发布时间】:2014-04-03 10:38:31
【问题描述】:

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

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

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

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

那么,有什么区别呢?为什么这本书没有使用while?虚假呼叫不是问题吗?

【问题讨论】:

  • 虽然条件变量的并发性对于Computer Science 来说是一个合适的主题,但您的问题实际上更多是关于 C++ 实现的行为方式。这是一道编程题,比较适合Stack Overflow,所以我迁移到那里。

标签: c++ multithreading concurrency condition-variable


【解决方案1】:

虚假唤醒始终是一个潜在问题。例如,看看这里的答案: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);
}

【讨论】:

    【解决方案2】:

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

    下面的论文描述了这些

    约翰·霍华德。 1976. 监视器中的信号。在第二届国际软件工程会议论文集(ICSE '76)中。 IEEE 计算机协会出版社,美国加利福尼亚州洛斯阿拉米托斯,47-52。

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

    有许多不同的学科。最初提出的一种是所谓的signal and wait,其中有信号的过程会立即继续(信号器必须等待)。使用这个纪律

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

    可以使用form,因为等待后谓词必须为真(前提是在发信号时为真)

    另外一个规则是signal and continue,在signaling过程继续的地方,signaled被放入monitor的一个entry queue。使用这个学科需要使用

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

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

    【讨论】:

    • 但是 OP 询问的是 C++11 条件变量,它们是信号并继续的。 if 可能适用于信号等待,但它与 C++11 变量无关。
    • @WanderingLogic:OP 询问为什么 Deitel 书中包含使用 if 的示例,特别是使用 ifwhile 之间的区别。我认为我的回答肯定与那个问题有关。
    猜你喜欢
    • 2022-01-23
    • 1970-01-01
    • 2021-09-24
    • 1970-01-01
    • 1970-01-01
    • 2021-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多