对于c++11,由于std::notify_all会导致虚假的唤醒,那么为什么std::notify_all会一直保持而不是std::notify_one呢?顺便说一句,std::notify_one会不会引起虚假的唤醒?
我对此表示怀疑:
当我调用std::condition_variable.wait/wait_for/wait_until和std::notify_XXX时,我的目的通常是实现线程同步化。也就是说,更多的线程被阻塞,直到另一个线程通知其中一个线程解除阻塞。
然后我可以调用notify_one来实现这一点,但是为什么会有另一个notify_all,它的目的是什么,或者notify_all适合什么情况?在我的情况下,当我调用notify_all时,它会唤醒所有等待的线程,然后只有一个线程实际上解除阻塞,而其他线程仍然处于阻塞状态,这是否称为虚假唤醒?如果notify_one也会称其为虚假唤醒呢?
发布于 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()则会挂起。
示例中有一个谓词,说明它应该等待,直到aborted是true,或者queue.empty()是false。
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;
}当关闭的时候,另一个线程通常会这样做:
aborted = true; // std::atomic<bool>
cv.notify_all();当我调用nitify_all时,它会唤醒所有等待的线程,然后只有一个线程实际上解除阻塞,而其他线程仍然处于阻塞状态,它是否称为虚假唤醒?
不是的。虚假的唤醒是一种随时可能发生的唤醒。如果您调用notify_all,等待的线程都会按顺序唤醒-而不是伪造的。
和notify_one是否也会称其为虚假唤醒?
它可能导致虚假的唤醒,但这将是一个实现细节。最好的做法是接受这样一个事实:线程可能在任何时候醒来,并且在它们醒来时只检查谓词。
能否精确地控制在等待线程中解除阻塞的位置(谁调用了没有谓词的
condition_variable.wait)?
在不检查谓词的情况下,线程唯一能确定的是它醒来了。如果是出于正确的理由,现在就不会了。
https://stackoverflow.com/questions/72600207
复制相似问题