首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >c++11 std::notify_all与伪唤醒

c++11 std::notify_all与伪唤醒
EN

Stack Overflow用户
提问于 2022-06-13 08:59:47
回答 1查看 120关注 0票数 1

对于c++11,由于std::notify_all会导致虚假的唤醒,那么为什么std::notify_all会一直保持而不是std::notify_one呢?顺便说一句,std::notify_one会不会引起虚假的唤醒?

我对此表示怀疑:

当我调用std::condition_variable.wait/wait_for/wait_untilstd::notify_XXX时,我的目的通常是实现线程同步化。也就是说,更多的线程被阻塞,直到另一个线程通知其中一个线程解除阻塞。

然后我可以调用notify_one来实现这一点,但是为什么会有另一个notify_all,它的目的是什么,或者notify_all适合什么情况?在我的情况下,当我调用notify_all时,它会唤醒所有等待的线程,然后只有一个线程实际上解除阻塞,而其他线程仍然处于阻塞状态,这是否称为虚假唤醒?如果notify_one也会称其为虚假唤醒呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-06-13 09:13:43

void std::condition_variable::wait(std::unique_lock<std::mutex>& lock);thread.condition/8.3

当调用notify_­one()或调用notify_­all()或伪造的发出信号时,该函数将解除阻塞。

因此,调用notify_­one()notify_­all()不是先决条件。它可以在没有任何调用的情况下解除阻塞。

以上引文取自"C++20第一次出版后草稿“,但自首次为C++11编写以来一直保持不变。

为什么会有另一个notify_all,它的目的是什么,或者notify_all适合什么情况?

当您希望所有等待的线程解除阻塞时。一个实际的情况是,是时候关机了。如果在wait中阻塞了线程,它们就永远不会完成,而join()则会挂起。

示例中有一个谓词,说明它应该等待,直到abortedtrue,或者queue.empty()false

代码语言:javascript
复制
bool pop_from_queue(T& item) {
    std::unique_lock<std::mutex> lock(mtx);
    while(queue.empty() && not aborted) cv.wait(lock);
    if(aborted) return false;        // time to shutdown
    // else pick an item from the queue
    item = std::move(queue.front());
    queue.pop();
    return true;
}

当关闭的时候,另一个线程通常会这样做:

代码语言:javascript
复制
aborted = true;   // std::atomic<bool>
cv.notify_all();

当我调用nitify_all时,它会唤醒所有等待的线程,然后只有一个线程实际上解除阻塞,而其他线程仍然处于阻塞状态,它是否称为虚假唤醒?

不是的。虚假的唤醒是一种随时可能发生的唤醒。如果您调用notify_all,等待的线程都会按顺序唤醒-而不是伪造的。

和notify_one是否也会称其为虚假唤醒?

它可能导致虚假的唤醒,但这将是一个实现细节。最好的做法是接受这样一个事实:线程可能在任何时候醒来,并且在它们醒来时只检查谓词。

能否精确地控制在等待线程中解除阻塞的位置(谁调用了没有谓词的condition_variable.wait )?

在不检查谓词的情况下,线程唯一能确定的是它醒来了。如果是出于正确的理由,现在就不会了。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72600207

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档