我有一个像这样的 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();
之前以及代码块的末尾解锁锁。这是不好的做法吗?确保以这种方式解锁锁的更好方法是什么?
答案 0 :(得分:4)
此答案假定 MLOCK
指的是标准互斥对象 std::mutex
。
互斥量必须被当前执行的线程锁定,否则行为未定义。
因此,当您的代码尝试解锁未锁定的互斥锁时,它具有未定义的行为。
这类问题最好使用标准类 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
对象的 unlock
或 mutex
成员函数。
答案 1 :(得分:1)
来自cppreference:
<块引用>std::mutex::unlock 解锁互斥锁。 互斥量必须被当前执行线程锁定,否则行为未定义。
所以不,你不能这样做。相反,您必须通过使用 std::lock_guard
或其他方式来跟踪您是否锁定了它。