【问题标题】:Does std::lock_guard release the mutex after constructed with std::adopt_lock option?使用 std::adopt_lock 选项构造后,std::lock_guard 是否释放互斥锁?
【发布时间】:2021-12-02 12:02:25
【问题描述】:

我知道我的问题与Why does std::lock_guard release the lock after using std::adopt_lock? 非常相似,但我看到的行为并非如此。这是我的代码:

#include <mutex>
#include <iostream>
using namespace std;

std::mutex m;
void fun2();
void fun1() {
    cout << "fun1" << endl;
    std::unique_lock<std::mutex> guard(m);
    cout << "lock mutex" << endl;
    fun2();
    if (guard.owns_lock()) {
        cout << "still holds mutex" << endl;
    }
    else {
        cout << "doesn't hold mutex" << endl;
    }
}
void fun2() {
    std::lock_guard<std::mutex> guard(m, std::adopt_lock);
    cout << "fun2" << endl;
}
int main(int argc, char* argv[]) {
    fun1();
    return 0;
}

这是我得到的结果:

fun1
lock mutex
fun2
still holds mutex

显然,fun1 中的 unique_lock 仍然持有互斥锁。所以我的问题是“std::lock_guard 在使用std::adopt_lock 选项构造后是否释放互斥锁?”。希望大家能帮我澄清一下这种情况。谢谢。

【问题讨论】:

  • std::adopt_lock 锁定策略假定线程已经拥有互斥锁的所有权。
  • 但是std::lock_guard退出fun2时会解锁析构函数中的互斥锁吗?
  • 是的,它会,但是fun1 内部的guard 不会知道互斥体状态的变化。在调用fun2 之后,您可以通过在fun1 中调用if (m.try_lock()) cout &lt;&lt; "locked\n"; 来检查互斥体状态变化
  • @TedLyngmo 如果是这样的话,try_lock 里面的fun1 是如何在我之前的评论代码中成功的?
  • @Harry 在致电fun2 之前,您是否尝试过try_lock?你不是try_locking 正确的事情。 if (guard.try_lock()) cout &lt;&lt; "locked\n"; 是正确的 try_lock

标签: c++ multithreading c++11 mutex unique-lock


【解决方案1】:

程序有未定义的行为。

你创建了两个守卫,他们都认为他们拥有mutex,他们都将拥有unlock。那是UB。

fun1 中使用m.lock() 而不是使用防护将是使其具有已定义行为的一种方法。

【讨论】:

  • 这是std::lock_guard:~lock_guard(){ _M_device.unlock(); }的析构函数的实现。据我所知,lock_guard 总是调用内部引用互斥锁_M_device 的解锁方法。所以它不会像你说的那样检查条件
  • @HuyNhatTran 我想人们必须深入挖掘并看看_M_device.unlock() 也做了什么。我面前没有那个。不过我会暂时删除它。你让我不确定:-)
  • C++20 标准明确表示析构函数~lock_guard() 应该(好像)调用pm.unlock()adopt_lock 案例也不例外。请参阅 thread.lock.guard p7。
  • @NateEldredge 确实如此。我更新了答案。
【解决方案2】:

当您构造std::unique_lock 来管理互斥锁时,您应该坚持使用它,除非您首先使用std::unique_lock::release 打破std::unique_lock 与互斥锁的关联。在您的示例中,当它仍然由 std::unique_lock 管理时,您触摸了原始互斥锁,这是错误的。

【讨论】:

  • 哦,我现在明白了。我已经阅读了std::unique_lock 的实现,发现std::unique_lock::owns_lock 返回了互斥锁的先前状态(当我调用std::unique_lock&lt;std::mutex&gt; guard(m) 时为true)。退出fun2时不知道互斥锁已解锁。谢谢你^^
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-24
  • 1970-01-01
  • 2011-03-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多