qbl*_*ble 15 c++ multithreading condition-variable thread-safety c++11
我需要同步std::condition_variable/condition_variable_any::notify_one吗?
据我所知,如果通知丢失是可以接受的 - 可以调用notify_one不受保护(例如通过互斥).
例如,我看到了以下使用模式(抱歉,不记得在哪里):
{
    {
        lock_guard<mutex> l(m);
        // do work
    }
    c.notify_one();
}
但是,我检查了libstdc ++来源,我看到:
condition_variable :: notify_one
void condition_variable::notify_one() noexcept
{
    int __e = __gthread_cond_signal(&_M_cond);
    // XXX not in spec
    // EINVAL
    if (__e)
        __throw_system_error(__e);
}
和condition_variable_any :: notify_one:
void condition_variable_any::notify_one() noexcept
{
    lock_guard<mutex> __lock(_M_mutex);
    _M_cond.notify_one();
}
这里是condition_variable_any的布局:
class condition_variable_any
{
    condition_variable _M_cond;
    mutex _M_mutex;
    // data end
即它只是condition_variable + mutex周围的薄包装.
所以,问题:
notify_one的互斥体的任一condition_variable_any或condition_variable?condition_variable_any::notify_one和condition_variable::notify_one不同?也许condition_variable::notify_one需要手动保护,但condition_variable_any::notify_one不是吗?它是libstdc ++ bug吗?Jon*_*ely 14
即它只是condition_variable + mutex周围的薄包装.
呃没有.仅仅因为它具有这些类型的成员并不能使它成为一个薄的包装器.试着了解它的实际功能,而不仅仅是其私有成员的类型.那里有一些非常微妙的代码.
- 对于condition_variable_any或condition_variable,不通过互斥锁保护notify_one是不是线程安全的?
是.
实际上,notify_one()使用锁定互斥锁进行调用将导致等待线程被唤醒,尝试锁定互斥锁,发现它仍然被通知线程锁定,然后返回休眠状态直到释放互斥锁.  
如果在notify_one()没有锁定互斥锁的情况下调用,则唤醒线程可以立即运行.
2为什么condition_variable_any的实现使用额外的互斥锁?
condition_variable_any可以与任何Lockable类型一起使用,不仅仅是std:mutex,但在libstdc ++中的内部使用a condition_variable,它只能用于std::mutex,因此它也有一个内部std::mutex对象.
因此,condition_variable_any使用两个互斥锁工作,用户提供的外部互斥和实现使用的内部互斥.
3为什么condition_variable_any :: notify_one和condition_variable :: notify_one的实现不同?也许condition_variable :: notify_one需要手动保护但是condition_variable_any :: notify_one不需要?它是libstdc ++ bug吗?
不,这不是一个错误.
该标准要求呼叫wait(mx)必须原子解锁mx和睡眠.libstdc ++使用内部互斥锁来提供原子性保证.必须锁定内部互斥锁,以避免在其他线程即将等待的情况下错过通知condition_variable_any.