繁体   English   中英

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

[英]Is using unique_lock in new scope equivalent to unlock call at the end of work with shared resource?

当开发人员在新范围内使用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 API中的方法unlock以这种方式实现此行为会更好:

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

这两个代码片段是否相同? 为什么开发人员使用第一个变体? 也许强调(使用括号)无法并行执行的代码?

在作用域末尾销毁对象时,将释放锁定。 这是RAII的重点。

使用RAII的好处是你不能忘记解锁,你离开范围并不重要。 例如,如果抛出异常,则仍将释放锁定。

如果您只需要锁定构造并在销毁时解锁,那么std :: scoped_lock是一个更简单/更合适的类。

我会说前一种方法更安全,更一致,更容易阅读。

首先考虑安全性:

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

如果你有不同的锁来获取/释放你忘记调用unlock()然后你可能最终尝试从同一个线程锁定相同的互斥锁 两次

这是未定义的行为,因此可能会被忽视,但会造成麻烦。

如果你在错误的锁变量上调用lock()unlock() lock2 ....(比如说在lock2而不是lock1 ?)可能性很可怕。

一致性:

此外,并非所有锁类型都具有.unlock()函数( std :: scoped_lockstd :: lock_guard ),因此最好与您的编码风格保持一致。

更易于阅读:

还可以更容易地看到哪些代码段使用锁,这使得对代码的推理更简单:

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
    }
}

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

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

#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
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM