【发布时间】:2018-02-24 01:43:52
【问题描述】:
我已经实现了一个类,它允许我将线程与条件变量同步。关于 notify_all 应该在锁内还是在锁外完成,我发现了相互矛盾的信息。我发现了两种方式构建的示例。
先释放锁的参数是为了防止等待线程在被通知释放后立即阻塞在互斥体上。
反对首先释放锁的论点是断言等待线程可能会错过通知。
发布功能的两个版本在这里:
// version 1 - unlock then notify.
void release(int address = 1)
{
{
std::lock_guard<std::mutex> lk(_address_mutex);
_address = address;
}
_cv.notify_all();
}
// version 2 - notify then unlock
void release(int address = 1)
{
std::lock_guard<std::mutex> lk(_address_mutex);
_address = address;
_cv.notify_all();
}
作为参考,等待代码如下所示:
bool wait(const std::chrono::microseconds dur, int address = 1)
{
std::unique_lock<std::mutex> lk(_address_mutex);
if (_cv.wait_for(lk, dur, [&] {return _address == address; }))
{
_address = 0;
return true;
}
return false;
}
在版本 1 中是否存在等待线程丢失通知的风险,其中允许互斥锁在 notify_all 之前超出范围?如果是这样,它是如何发生的? (这对我来说是如何导致错过通知的并不明显。)
我可以清楚地看到在通知期间保持互斥锁如何导致等待线程立即进入等待状态。但是,如果它可以防止错过通知,这是一个很小的代价。
【问题讨论】:
-
理论上在调用 notify 之前释放锁更有效,但实际上大多数编译器优化了如果你不这样做可能发生的潜在低效率。
-
两者都可以,见手册pthread_cond_broadcast,见类似问题stackoverflow.com/questions/17101922/…直播时不用锁。
标签: c++ multithreading