f1m*_*sch 2 c++ locking condition-variable c++11 spurious-wakeup
使用 c++11。既然std::notify_all
会导致虚假唤醒,那么为什么std::notify_all
会保留而不是std::notify_one
一直存在呢?std::notify_one
顺便说一句,可能会导致虚假唤醒吗?
阐述一下我的疑惑:
当我调用std::condition_variable.wait/wait_for/wait_until
and时std::notify_XXX
,我的目的通常是实现线程同步。也就是说,更多的线程阻塞等待,直到另一个线程通知只有其中一个线程解除阻塞。
那么我就可以调用notify_one
来实现这一点,但是为什么还有另一个notify_all
,它的目的是什么,或者notify_all
适合什么情况?在我的情况下,当我调用 时notify_all
,它会唤醒所有等待线程,然后只有一个线程真正解除阻塞,而其他线程仍然阻塞,这是否称为虚假唤醒?如果notify_one
也会调用虚假唤醒?
void std::condition_variable::wait(std::unique_lock<std::mutex>& lock);
从\n thread.condition
/8.3开始:
\n\n当通过调用
\nnotify_\xc2\xadone()
或 或虚假地调用notify_\xc2\xadall()
发出信号时,该函数将解除阻塞。
所以调用notify_\xc2\xadone()
ornotify_\xc2\xadall()
并不是先决条件。它可以在不调用任何一个的情况下解锁。
上面的引用来自“C++20 第一个发布后草案”,但自从首次为 C++11 编写以来一直保持不变。
\n\n\n为什么还有另一个
\nnotify_all
,它的用途是什么,或者notify_all
适合什么情况?
当您希望所有等待线程解除阻塞时。实际情况是需要关闭时。如果线程被阻塞,wait
它们将永远不会完成并且join()
它们将挂起。
带有谓词的示例表示它应该等到aborted
istrue
或queue.empty()
is false
:
bool pop_from_queue(T& item) {\n std::unique_lock<std::mutex> lock(mtx);\n while(queue.empty() && not aborted) cv.wait(lock);\n if(aborted) return false; // time to shutdown\n // else pick an item from the queue\n item = std::move(queue.front());\n queue.pop();\n return true;\n}\n
Run Code Online (Sandbox Code Playgroud)\n当需要关闭时,另一个线程通常会执行以下操作:
\naborted = true; // std::atomic<bool>\ncv.notify_all();\n
Run Code Online (Sandbox Code Playgroud)\n\n\n当我调用nitify_all时,它会唤醒所有等待线程,然后只有一个线程真正解锁,其他线程仍然阻塞,这是否称为虚假唤醒?
\n
不。虚假唤醒是指随时可能发生的唤醒。如果您调用notify_all
,等待的线程将按顺序全部唤醒 - 而不是虚假的。
\n\n如果notify_one也会调用虚假唤醒?
\n
它可能会导致虚假唤醒,但这将是一个实现细节。最好的办法是接受线程可能随时唤醒的事实,并在唤醒时检查谓词。
\n\n\n我可以精确控制等待线程中的何处解除阻塞(谁
\ncondition_variable.wait
在没有谓词的情况下调用)?
在不检查谓词的情况下,线程唯一确定的事情就是它已醒来。无论出于正确与否,现在都不会了。
\n 归档时间: |
|
查看次数: |
385 次 |
最近记录: |