在代码的其他部分使用 lock_gard 和不使用它的相同互斥锁是否安全

is it safe to use the same mutex with lock_gard and without it in other parts of code

我有命名空间,在该命名空间下,不同线程将调用 func1 和 func2。

#include<thread>
namespace test{

    std::mutex mu;

    void func1(){
        std::lock_guard<mutex>lock(mu);
       //the whole function needs to be protected
    }

    void func2() {
        mu.lock();
        //some code that should not be executed when func1 is executed
        mu.unlock();
        //some other code
    }
}

使用此互斥量(一次与 lock_guard 及其外部)来保护这些关键部分是否安全?如果不是如何实现这个逻辑?

当至少涉及两个 mutex 或单个 mutex 由于某种原因没有永远解锁时,就会发生死锁。

第二个函数的唯一问题是,在异常情况下锁不会被释放。

您可以简单地使用 lock_guard 或任何其他被销毁的东西(并解锁 dtor 的互斥量)来避免像您对第一个函数所做的那样的情况。

lock_guard所做的一切都是为了保证在破坏时解锁。当函数可以采用多条路径(想想异常!)而不是必需时,让代码正确是很方便的。此外,它建立在 "regular" lock()unlock() 函数之上。综上,安全。

是的,您可以在不同的函数中将不同的守卫实例(例如 lock_guard、unique_lock 等)与 std::mutex 有效地混合和匹配。我偶尔 运行 遇到的一种情况是,当我想对大多数方法使用 std::lock_guard 时,但是 std::condition_variable 的使用期望其 wait 方法使用 std::unique_lock

为了详细说明 Oblivion 所说的内容,我通常会在函数中引入一个新的作用域块,以便 std::lock_guard 的用法保持一致。示例:

void func2() {

    {  // ENTER LOCK
        lock_guard<std::mutex> lck;

       //some code that should not be executed when func1 is executed

    } // EXIT LOCK

    // some other (thread safe) code 
}

使用上述模式的优点是,如果在锁定代码的临界区内有任何异常抛出,lck 的析构函数仍将被调用,从而解锁互斥量.