【问题标题】:std::mutex best practicestd::mutex 最佳实践
【发布时间】:2019-06-18 08:57:21
【问题描述】:

因为当抛出异常时,唯一能确保运行的代码是析构函数,这样的代码可能会产生内存泄漏

std::mutex foo;
foo.lock();
// My code which might throw an exception
foo.unlock();

做类似的事情是最佳做法还是可能有其他更好的选择? 这个想法是利用 RAII 来确保在抛出异常时释放互斥锁。

std::mutex foo;
{
    std::lock_guard<std::mutex>(foo);
    // My code which might throw an exception
}

【问题讨论】:

  • 嗯,通常这是最佳实践。如果你想在作用域结束之前解锁它,你可以改用std::unique_lock,但是手动管理互斥锁没有任何好处(除了头痛和错误)。
  • std::lock_guard&lt;std::mutex&gt;(foo); 不会保护任何东西,因为未命名的临时变量会立即被销毁,因此当互斥锁未锁定时,// My code 将被执行。

标签: c++ exception raii


【解决方案1】:

做类似的事情是最佳实践吗?

std::mutex foo;
{
    std::lock_guard<std::mutex>(foo);
    // My code which might throw an exception
}

不!您在这里创建了一个未命名的临时变量,其生命周期在行尾结束。相反,请确保对象有一个名称,使其生命周期符合其范围。

std::mutex foo;
{
    std::lock_guard<std::mutex> NEVER_FORGET_THIS_NAME(foo);
    // My code which might throw an exception
}

但除此之外,通常 - 是的,在这种情况下使用 RAII 是一种很好的做法。还要注意 unnamed-lockguard 错误并不少见,看看here

【讨论】:

  • 我不想成为挑剔者,但只有在使用 {} 的情况下才能构造临时对象 - std::lock_guard&lt;std::mutex&gt;{foo}; 在这种情况下我们有临时的 lock_guard,但在这个 std::lock_guard&lt;std::mutex&gt;(foo);代码无法编译,因为没有不带参数的 lock_guard 构造函数 - 需要互斥锁。代码std::unique_lock&lt;std::mutex&gt;(foo) 创建了 foo 实例,其 ctor 不接受 mutex,因此构造中没有锁定,销毁时也没有解锁,但 foo 因为 unique_lock 一直存在到作用域结束。 demo
【解决方案2】:

始终使用lock_guard 以确保互斥锁将被释放。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-18
    • 1970-01-01
    • 1970-01-01
    • 2019-04-09
    • 2020-11-02
    • 2017-03-28
    • 2010-09-05
    • 2014-12-21
    相关资源
    最近更新 更多