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

ime*_*kon 2 c++ mutex

我有这个课(简化):

// 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);
}
Run Code Online (Sandbox Code Playgroud)

如果我打电话来处理,我得到一个例外:

Microsoft C++ exception: std::system_error at memory location 0x006FF16C.
Run Code Online (Sandbox Code Playgroud)

锁定同一线程中的同一个锁会导致此异常.除了例外,我怎么能这样做?我想添加一个标志:

volatile bool alreadyLocked;
Run Code Online (Sandbox Code Playgroud)

改变内在:

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

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

Vit*_*meo 12

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

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

从cppreference:

调用线程拥有recursive_mutex一段时间,该时间段在成功调用lock或启动时启动try_lock.在此期间,线程可能会对lock或进行额外调用try_lock.当线程进行匹配的解锁次数时,所有权期限结束.

当一个线程拥有一个线程时recursive_mutex,所有其他线程将阻塞(用于调用lock)或接收一个错误的返回值(for try_lock)如果它们试图声明所有权recursive_mutex.


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