当在其他地方使用相同的互斥锁时,等待/通知unique_lock互斥锁是否安全lock_guard

Is it safe to wait/notify on unique_lock mutexes when same mutexes are used with lock_guard on somewhere else?

本文关键字:lock 其他 unique 通知 是否 guard 安全 等待 方使用      更新时间:2023-10-16

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

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可以使用同一个互斥对象相互配合吗?

std::unique_lockstd::lock_guard 都将关联的互斥锁锁定在构造函数中,并在析构函数中将其解锁。

std::unique_lock

成员函数

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

std::lock_guard也是如此:

成员函数

(构造函数(构造一个lock_guard,可以选择锁定给定的互斥体
(析构函数(销毁lock_guard对象,解锁底层互斥锁

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

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

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

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

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

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

相关文章: