0

我正在使用以下等待/信号方式让线程相互通知。

std::condition_variable condBiz;
std::mutex mutexBar;
..
void Foo::wait()
{
    std::unique_lock<std::mutex> waitPoint(mutexBar);
    if (waitPoint.owns_lock())
    {
        condBiz.wait(waitPoint);
    }
}
void Foo::signal()
{
    std::unique_lock<std::mutex> waitPoint(mutexBar);
    condBiz.notify_all();
}
void Foo::safeSection(std::function<void(void)> & f)
{
   std::unique_lock<std::mutex> waitPoint(mutexBar); 
   f();
}

然后将锁定/解锁机制从 unique_lock 转换为 lock_guard,因为我没有返回 unique_lock 以在其他地方使用(等待/信号除外),并且据说 lock_guard 的开销更少:

void Foo::safeSection(std::function<void(void)> & f)
{
   std::lock_guard<std::mutex> waitPoint(mutexBar);  // same mutex object
   f();
}

它有效。

这适用于所有平台还是看起来适用于当前平台?unique_lock 和 lock_guard 可以使用相同的互斥对象相互工作吗?

4

2 回答 2

2

std::unique_lock并在构造函数中锁定关联的互斥std::lock_guard体并在析构函数中解锁。

std::unique_lock

成员函数

(构造函数)构造一个 unique_lock,可选择锁定提供的互斥锁
(析构函数)解锁关联的互斥锁,如果拥有

和同样的std::lock_guard

成员函数

(构造函数)构造一个lock_guard,可选地锁定给定的互斥锁
(析构函数)解构lock_guard对象,解锁底层互斥锁

由于两者的行为相同,当用作 RAII 样式包装器时,我认为将它们一起使用没有任何障碍,即使使用相同的互斥锁也是如此。

于 2018-03-18T16:32:00.970 回答
2

在您的帖子的评论中已经指出,检查 Foo::wait() 中是否拥有 unique_lock 是没有意义的,因为此时关联的互斥锁必须由锁拥有才能使线程继续进行。

相反,您的条件变量应该检查一些有意义的条件,并且它应该在 while 循环中或通过使用 condition_variable::wait 的重载来执行此操作,该重载将谓词作为其第二个参数,这是 C++ 标准所要求的:

while (!pred()) wait(lock);

在 while 循环中检查谓词的原因是,除了条件可能已经满足因此不需要等待这一事实之外,即使没有发出信号,条件变量也可能会虚假地唤醒。

除此之外,没有理由信号线程不应该对关联的互斥锁使用 lock_guard。但我不清楚你想做什么。

于 2018-03-18T16:18:09.363 回答