如何在同一个线程上使用同一个互斥锁两次锁定?

新手上路,请多包涵

我有这个类(简化):

 // thing.h

#include <mutex>

class Thing
{
public:
    void process();
    void inner();

private:
    std::mutex lock;
};

// thing.cpp

#include "Thing.h"

using namespace std;

void Thing::process()
{
    lock_guard<mutex> locking(lock);

    inner();
}

void Thing::inner()
{
    lock_guard<mutex> locking(lock);
}

如果我调用处理,我会得到一个异常:

 Microsoft C++ exception: std::system_error at memory location 0x006FF16C.

锁定同一线程中的同一锁会导致此异常。我怎么能做到这一点,没有例外?我想过添加一个标志:

 volatile bool alreadyLocked;

将内部更改为:

 void Thing::inner()
{
     if (!alreadyLocked)
     {
         lock_guard<mutex> locking(lock);
         alreadyLocked = true;
         ...something magic happens here...
         alreadyLocked = false;
     }
}

然而,这感觉很脆弱……有没有正确的方法来做到这一点?

原文由 imekon 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.2k
1 个回答

首先, volatile 变量 不是线程安全的。您必须使用 std::atomic<T> 才能拥有线程安全的变量。 volatile 与线程安全无关。

要解决您的问题,您可以使用 std::recursive_mutex ,可以从同一个线程多次锁定/解锁。

来自 cppreference:

调用线程在成功调用 locktry_lock 时开始拥有 recursive_mutex 一段时间。在此期间,线程可能会额外调用 locktry_lock 。当线程进行匹配数量的解锁调用时,所有权期结束。

当一个线程拥有一个 recursive_mutex 时,所有其他线程将阻塞(对于调用 lock )或接收一个错误的返回值(对于 try_lock )声称拥有 recursive_mutex


此外,请考虑重构您的代码,以便不需要两次锁定互斥锁。改进您的设计可能会避免这个问题。

原文由 Vittorio Romeo 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题