c++ - 为什么信号量的条件/互斥实现在其 "while"函数中需要一个 "wait()"循环?

标签 c++ boost

我一直在仔细研究以下 SO 问题的公认答案:C++0x has no semaphores? How to synchronize threads?

在那个答案的信号量实现中,这里是 wait() 函数的实现:

void wait()
{
    boost::mutex::scoped_lock lock(mutex_);
    while(!count_)
        condition_.wait(lock);
    --count_;
}

我试图理解 while(!count_) 条件的目的。

另一个 SO 问题 (How does this implementation of semaphore work?) 的答案表明,当在条件变量上调用 notify_one() 时,多个 线程是可能的等待该条件变量将被唤醒 - 因此需要 while 循环。我想确认这一点 - 是完整和/或正确的答案,还是有其他原因需要 while 循环?

如果唤醒了多个线程,哪个线程拥有互斥量?我想得越多,如果多个线程由于一次调用 notify_one() 就可以唤醒,这似乎越不明确。两个被唤醒的线程是否都不可能看到 count_ 值高于 0,并继续递减 count_,导致 count_ 小于 0 的值,并且违背了信号量的目的(和正确性)?

最佳答案

可能有 spurious wakeups ,或者 notify_one 可能会因为实现细节而唤醒多个线程,正如您已经提到的那样。

虽然唤醒多个线程并不意味着它们都可以同时进入 protected 部分,它只是意味着当ThreadA释放锁时,ThreadB(在前面的例子中与ThreadA一起被唤醒)也可以进入 protected 部分。此时 ThreadA 已经完成了它的工作,因此 ThreadB 不会看到 count 变量处于与 ThreadA 发现它时相同的状态。

关于c++ - 为什么信号量的条件/互斥实现在其 "while"函数中需要一个 "wait()"循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13412110/

相关文章:

c++ - 如何使用 boost 序列化检测无效输入?

c++ - 创建大图像

c# - 将 C# 委托(delegate)传递给 C++/CLI 包装器

c++ - 引用是跨二进制边界工作的,还是必须使用指针?

c++ - 使用 CreateProcess 尽可能使用单个命令参数调用 exec* 函数

c++ - 编译器错误 :falied to determine size of array size identifier

c++ - boost::posix_time::microsec_clock 以微秒分辨率加倍秒

c++ - 使用 boost::iostreams 逐字节解析二进制文件

c++ - Boost:asio 获取异常

c++ - 尝试等待 boost::condition_Variable 时出现 "unique_lock has no mutex: Operation not permitted"错误