问题描述
我需要同步 std :: condition_variable / condition_variable_any :: notify_one
?
可以看到,如果丢失通知是可以接受的 - 可以调用 notify_one
不受保护(例如mutex)。
As far as I can see, if lost of notifications is acceptable - it is OK to call notify_one
not protected (by mutex for example).
例如,我看到以下使用模式(对不起,不记得在哪里):
For instance, I saw following usage patterns (sorry, don't remember where):
{
{
lock_guard<mutex> l(m);
// do work
}
c.notify_one();
}
但是,我检查了libstdc ++来源,我看到:
But, I inspected libstdc++ sources, and I see:
void condition_variable::notify_one() noexcept
{
int __e = __gthread_cond_signal(&_M_cond);
// XXX not in spec
// EINVAL
if (__e)
__throw_system_error(__e);
}
和:
void condition_variable_any::notify_one() noexcept
{
lock_guard<mutex> __lock(_M_mutex);
_M_cond.notify_one();
}
这里是condition_variable_any的布局:
And here is layout of condition_variable_any:
class condition_variable_any
{
condition_variable _M_cond;
mutex _M_mutex;
// data end
所以,问题:
- >通过mutex为
condition_variable_any
或condition_variable不能保护
notify_one
/ code>? - 为什么condition_variable_any的实现使用额外的互斥?
- 为什么实现
condition_variable_any :: notify_one
和condition_variable :: notify_one
不同?可能condition_variable :: notify_one
需要手动保护,但condition_variable_any :: notify_one
不会?是libstdc ++错误吗?
- Is it thread-safe to not protect
notify_one
by mutex for eithercondition_variable_any
orcondition_variable
? - Why implementation of condition_variable_any uses additional mutex?
- Why implementation of
condition_variable_any::notify_one
andcondition_variable::notify_one
differs? Maybecondition_variable::notify_one
requires manual protection butcondition_variable_any::notify_one
doesn't? Is it libstdc++ bug?
推荐答案
Er,no。只是因为它有那些类型的成员不会使它是一个薄包装。尝试了解它实际上是什么,不只是它的私人成员的类型。
Er, no. Just because it has members of those types doesn't make it a thin wrapper. Try to understand what it actually does, not just the types of its private members. There's some quite subtle code there.
- 它是线程安全的,无法通过互斥锁保护notify_one condition_variable_any或condition_variable?
可以。
事实上,调用 notify_one()
并锁定互斥锁将导致等待线程被唤醒,尝试锁定互斥锁,发现它仍然被通知线程锁定,回到睡眠状态,直到互斥体释放。
In fact, calling notify_one()
with the mutex locked will cause waiting threads to wake up, attempt to lock the mutex, find it is still locked by the notifying thread, and go back to sleep until the mutex is released.
如果调用 notify_one()
而不锁定互斥锁,则唤醒线程可以立即运行。
If you call notify_one()
without the mutex locked then the waking threads can run immediately.
condition_variable_any
可用于任何可锁定类型,而不仅仅是 std:mutex
libstdc ++中的一个使用 condition_variable
,它只能与 std :: mutex
一起使用, std :: mutex
对象。
condition_variable_any
can be used with any Lockable type, not just std:mutex
, but internally the one in libstdc++ uses a condition_variable
, which can only be used with std::mutex
, so it has an internal std::mutex
object too.
所以 condition_variable_any
不,这不是错误。
标准要求调用 wait(mx)
必须原子解锁 mx
并睡眠。 libstdc ++使用内部互斥来提供原子性的保证。必须锁定内部互斥锁以避免错过通知,如果其他线程只是要等待 condition_variable_any
。
The standard requires that calling wait(mx)
must atomically unlock mx
and sleep. libstdc++ uses the internal mutex to provide that guarantee of atomicity. The internal mutex must be locked to avoid missed notifications if other threads are just about to wait on the condition_variable_any
.
这篇关于我需要同步std :: condition_variable / condition_variable_any :: notify_one的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!