c++ - 解锁无主互斥体

标签 c++

我创建了以下类,它提供了 acquire_lock()release_lock() 函数

class LockableObject {

public:

    void acquire_lock() {
        std::unique_lock<std::mutex> local_lock(m_mutex);
        m_lock = std::move(local_lock);
    }

    void release_lock() {
        m_lock.unlock();
    }

private:

    std::mutex m_mutex;

    std::unique_lock<std::mutex> m_lock;
};

此类提供了acquire_lockrelease_lock函数。我有多个线程访问同一个对象,并在执行任何操作之前调用 acquire_lock ,然后在完成后调用 release_lock ,如下所示。

void ThreadFunc(int ID, LockableObject* lckbleObj)
{
    for (int i = 0; i < 1000; i++)
    {
        lckbleObj->acquire_lock();
        std::cout << "Thread with ID = " << ID << "doing work" << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
        lckbleObj->release_lock();
    }
}



void main()
{
    const int numThreads = 10;
    std::thread workerThreads[numThreads];
    LockableObject *testObject = new LockableObject();

    for (int i = 0; i < numThreads; i++)
    {
        workerThreads[i] = std::thread(ThreadFunc, i, testObject);
    }

    for (int i = 0; i < numThreads; i++)
    {
        workerThreads[i].join();
    }
}

acquire_lock 函数中,我首先尝试使用本地堆栈 std::unique_lock 对象锁定底层互斥体 (m_mutex)在构造函数中传递它(m_mutex)。我假设一旦 std::unique_lock 的构造函数返回,它就锁定了互斥体,然后我将堆栈上的 unique_lock 移动到成员变量 m_lock

这个程序在一些基本方面存在缺陷,在调用release_lock期间将导致“解锁无主互斥体”,我似乎错过了一些基本的东西std::unique_lock 我正在寻找有人来纠正我的理解。

最佳答案

请参阅我关于缺少 std::defer_lock 的评论在构造函数中。但您的代码中也存在竞争条件。

acquire_lock函数修改 m_lockm_mutex 的保护下互斥体。这样,为了保证线程安全,其他线程不能修改m_lock除非按住m_mutex .

但是release_lock函数修改m_lock当它释放该互斥体时。因此,您在 m_lock 上没有正确的同步。 .

这有点难以理解。这是问题代码:

    m_lock.unlock();

请注意,当输入此函数时,m_mutex被锁定,但在执行期间,它都修改 m_lock并发布m_mutex没有特别保证的顺序。但是m_mutex保护m_lock 。所以这是一个竞争条件并且是不允许的。

可以按如下方式修复:

void release_lock() {
    std::unique_lock<std::mutex> local_lock = std::move(m_lock);
    local_lock.unlock();
}

现在,第一行代码修改 m_lock但完全以 m_mutex 运行握住。这避免了竞争条件。

unlock如果需要,可以将其移除。 local_lock的析构函数会做的。

顺便说一句,我建议更改 API。与其提供锁定和解锁调用,不如有一种方法来创建一个拥有该对象锁的对象。您甚至可以使用std::unique_lock<LockableObject>如果你想。为什么要创建一个比标准提供的 API 更糟糕的新 API?

关于c++ - 解锁无主互斥体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59638470/

相关文章:

c++ - 什么是 int() 调用?

C++ 'class' 类型重定义

c++ - 模板类内部运算符在该类的不同特化对象之间的特化

c++ - 在无向图中查找连接组件的数量

c++ - 指数加权平均 C++ 嵌套 for 循环

c++ - 是否可以根据方法签名中某个参数的存在或不存在来进行模板特化?

c++ - 在运行时将指针推送到 vector C++

c++ - 如何检查文件是否被压缩?

c++ - 我应该选择哪个 C++ 信号/插槽库?

c++ - 生成文件不起作用