C++ 在新范围中使用unique_lock是否等同于在共享资源的工作结束时解锁调用?

C++ 在新范围中使用unique_lock是否等同于在共享资源的工作结束时解锁调用?,c++,multithreading,c++11,C++,Multithreading,C++11,当开发者在自动解锁互斥锁的新范围中使用std::unique_lock时,我看到了很多代码示例: ... // do some staff { std::unique_lock<std::mutex> lock(shared_resource_mutex); // do some actions with shared resource } // do some staff ... 这两段代码是等价的吗?开发人员使用第一个变体的目的是什么?也许要强调(使用括号)不能并行执行

当开发者在自动解锁互斥锁的新范围中使用
std::unique_lock
时,我看到了很多代码示例:

...
// do some staff
{
  std::unique_lock<std::mutex> lock(shared_resource_mutex);
  // do some actions with shared resource
}
// do some staff
...

这两段代码是等价的吗?开发人员使用第一个变体的目的是什么?也许要强调(使用括号)不能并行执行的代码

当对象在作用域末尾被销毁时,锁被释放。这就是RAII的全部要点

使用RAII的好处是,您不能忘记解锁,无论您如何离开范围。例如,如果抛出异常,锁仍将被释放


如果您只需要在构造时锁定,在销毁时解锁,那么就可以使用更简单/更合适的类。

我认为前一种方法更安全、更一致、更易于阅读

<强>首先考虑安全性:< /强>

void function()
{
    std::unique_lock<std::shared_mutex> lock(mtx);

    // exclusive lock stuff

    lock.unlock();

//  std::shared_lock<std::shared_mutex> lock(mtx); // whoops name in use
    std::shared_lock<std::shared_mutex> lock2(mtx);

    // read only shared lock stuff here

    lock2.unlock(); // what if I forget to do this?

    lock.lock(); // if I forgot to call lock2.unlock() undefined behavior

    // back to the exclusive stuff

    lock.unlock();  
}

这两种方法都是正确的,您可以根据具体情况选择其中一种。例如,当使用条件变量/锁组合时,能够显式锁定和解锁锁通常很有用

我发现另一种方法既有表现力又安全:

#include <mutex>

template<class Mutex, class Function>
decltype(auto) with_lock(Mutex& m, Function&& f)
{
    std::lock_guard<Mutex> lock(m);
    return f();
}

std::mutex shared_resource_mutex;

void something()
{
    with_lock(shared_resource_mutex, [&]
    {
        // some actions
    });

    // some other actions
}
#包括
模板
decltype(自动)带锁(互斥锁和m、函数和f)
{
标准:锁和防护锁(m);
返回f();
}
std::互斥体共享资源互斥体;
使某物无效
{
带锁(共享资源互斥,[&]
{
//一些行动
});
//其他一些行动
}

“例如,如果抛出异常,锁仍将被释放。”但对于另一个变体也是如此。是的,我知道RAII,但我说的是另一件事。unique_lock有一个unlock方法,可以尽早(在可能的情况下)释放资源上的锁,以改进并行化,即使在unlock之前抛出异常,一切都会正常。询问人们为什么使用{}来执行此操作而不是解锁调用。是的,但在这种情况下,您将有两种不同的方式来释放锁,而不是仅使用一种。现在,初学者可能看不到互斥锁是在哪里发布的。同时调用unlock,初学者可能会认为锁不会在抛出时释放。引入新的作用域通常是可能创建子函数的标志。。。
void function()
{
    {
        std::unique_lock<std::shared_mutex> lock(mtx);

        // exclusive lock stuff
    }

    {
        std::shared_lock<std::shared_mutex> lock(mtx);

        // read only shared lock stuff here
    }

    {
        std::unique_lock<std::shared_mutex> lock(mtx);

        // back to the exclusive stuff
    }
}
#include <mutex>

template<class Mutex, class Function>
decltype(auto) with_lock(Mutex& m, Function&& f)
{
    std::lock_guard<Mutex> lock(m);
    return f();
}

std::mutex shared_resource_mutex;

void something()
{
    with_lock(shared_resource_mutex, [&]
    {
        // some actions
    });

    // some other actions
}