首页 > 解决方案 > 在互斥锁未锁定时调用解锁?

问题描述

我有一个这样的 if 分支:

  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();

我想确保在调用之前elect_new_primary以及在代码块的末尾解锁锁。这是不好的做法吗?确保以这种方式解锁锁的更好方法是什么?

标签: c++lockingmutex

解决方案


这个答案假设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

您应该很少求助于直接调用对象的lockunlock成员函数mutex


推荐阅读