【发布时间】:2017-04-22 17:45:28
【问题描述】:
这是一段将从多个线程调用的代码。 std::condition_variable::wait 的谓词对于每个线程都会略有不同,但不会改变问题。
std::unique_lock<std::mutex> lock{connection_mutex};
cv.wait(lock,
[conn = shared_from_this()]
{
return conn->connection_is_made();
}
);
//do some stuff
lock.unlock();
我在cppreference读到这篇文章
当通知条件变量、超时过期或发生虚假唤醒时,线程被唤醒,互斥量被原子地重新获取。如果唤醒是虚假的,线程应该检查条件并继续等待。
据我所知,lock 将被锁定,然后会检查谓词 lambda,如果它返回 true,lock 将保持锁定状态,我可以在此保护下继续做一些事情互斥体。当std::condition_variable 被notify_one() 成员函数通知时,这是非常有意义的。
但是当std::condition_variable 被notify_all() 通知时会发生什么?如果所有线程都被唤醒并且比“排队等待”来锁定互斥锁,然后才检查谓词返回什么,或者他们可能会做其他事情,我无法在文档中找到。
编辑:在看到下面的 cmets 后,我开始思考。 std::condition_variable::wait 期望 std::unique_lock 作为它的第一个参数,当 std::condition_variable::wait 在通知后被唤醒时 - std::unique_lock 将被重新获取。现在,如果多个线程正在等待同一个通知,那么当最终在特定的 std::condition_variable 上调用 notify_all() 时,只有 1 个线程能够锁定互斥锁,所有其他线程将重新进入睡眠状态。因此,如果 notify_all() 成员函数与 notify_one() 具有相同的效果,但效率较低,我根本看不到它有任何意义。我的意思是,如果必须重新获取互斥锁
一个线程通过std::condition_variable::wait,那么所有等待的线程不可能同时完成。
【问题讨论】:
-
如果您询问通知顺序,那么这可能会有所帮助:stackoverflow.com/questions/15912322/…
-
感谢您的回答,但在这种情况下,我并不担心永远不会收到 notify_all() 信号。我只想知道多个线程在等待同一个condition_variable时是怎么做的,然后通过notify_all()接收通知,然后尝试获取同一个mutex。
-
这取决于操作系统调度程序。您无法知道哪个线程首先获得互斥锁。
-
他们在排队吗? 1 个线程得到它,做它的事情,当互斥锁被释放时,另一个线程立即重新获取互斥锁并检查它的谓词等等,直到所有等待的线程重新获得互斥锁?
-
根据cppreference,所有线程都被唤醒。但是,如果他们只是要为互斥锁“排队”,那么除了一个之外,其他所有人都会回去睡觉。那么在那种情况下,为什么要调用全部通知而不是通知一个呢?如果所有等待的线程可以同时取得进展,Notify all 很好。
标签: c++ multithreading c++11