stc :: condition_variable_any的libc ++实现

Cur*_*ous 9 c++ multithreading condition-variable thread-safety c++11

条件变量应该具有相对于的单个顺序notify()unlock_sleep()(wait()在互斥锁被解锁并且线程作为一个原子操作序列休眠的操作中使用的虚函数调用)操作.要使用任意可锁定实现此功能,std::condition_variable_any通常在内部使用另一个互斥锁(以确保原子性和睡眠状态)

如果内部unlock_sleep()notify()(notify_one()notify_all())操作相对于彼此不是原子操作,则冒着线程解锁互斥锁的风险,另一个线程发出信号,然后原始线程将进入休眠状态并且从不唤醒.

我正在阅读std :: condition_variable_any的libstdc ++和libc ++实现,并注意到libc ++实现中的这段代码

{lock_guard<mutex> __lx(*__mut_);}
__cv_.notify_one();
Run Code Online (Sandbox Code Playgroud)

内部互斥锁被锁定,然后在信号操作之前立即解锁.这不是我上面描述的问题吗?

libstdc ++似乎已经做到了这一点

Mic*_*urr 1

notify_oneC++11 及更高版本的标准明确规定“和的执行notify_all应该是原子的”。因此,从某种意义上说,我认为您是正确的,内部互斥体应该在平台的底层条件变量通知调用期间保持不变(例如pthread_cond_signal()

但是,我不认为 libc++ 实现会导致错过通知,因为如果通知线程在调用(或)wait()时没有在等待线程传递的锁上同步(或两个线程之间的其他同步),就没有办法确保两个线程中的哪一个是“第一个”通知或等待的线程。因此,如果在 libc++ 的当前实现中可能会错过通知,那么如果将 libc++ 更改为在其对平台通知 API 的调用中保持内部锁定,也可能会错过通知。notify_one()notify_all()

所以我认为 libc++ 可以调用“好像”规则来表示notify_one()/的实现notify_any()“足够原子”。