未锁定时在互斥锁上调用解锁?

时间:2020-12-18 23:10:26

标签: c++ locking mutex

我有一个像这样的 if 分支:

Base::f()

我想确保在调用 MLOCK.lock(); if (CPRIMES[snode->cid] == snode) { CPRIMES.erase(snode->cid); log("[remove_storage_node] Node " + kv_addr + " dropped as primary", VB); MLOCK.unlock(); elect_new_primary(snode->cid); } MLOCK.unlock(); 之前以及代码块的末尾解锁锁。这是不好的做法吗?确保以这种方式解锁锁的更好方法是什么?

2 个答案:

答案 0 :(得分:4)

此答案假定 MLOCK 指的是标准互斥对象 std::mutex

来自std::mutex::unlock

<块引用>

互斥量必须被当前执行的线程锁定,否则行为未定义。

因此,当您的代码尝试解锁未锁定的互斥锁时,它具有未定义的行为。

这类问题最好使用标准类 std::unique_lock 来解决。这个类将管理锁,当它自己的生命周期结束时,如果它仍然被锁定,它将确保解锁互斥锁。

例如:

#include <mutex>

std::mutex m;

void foo(bool b)
{
    // Lock `m` and take ownership of that lock
    std::unique_lock<std::mutex> lock{m};

    if(b) { 
        // Unlocks `m`
        lock.unlock();
    }
}   // `m` will be unlocked if it wasn't unlocked previously

您应该很少求助于直接调用 lock 对象的 unlockmutex 成员函数。

答案 1 :(得分:1)

来自cppreference

<块引用>

std::mutex::unlock 解锁互斥锁。 互斥量必须被当前执行线程锁定,否则行为未定义。

所以不,你不能这样做。相反,您必须通过使用 std::lock_guard 或其他方式来跟踪您是否锁定了它。