【问题标题】:What special purpose does unique_lock have over using a mutex?unique_lock 使用互斥锁有什么特殊用途?
【发布时间】:2014-07-16 15:02:46
【问题描述】:

我不太清楚为什么std::unique_lock<std::mutex> 比只使用普通锁有用。我正在查看的代码中的一个示例是:

{//aquire lock

        std::unique_lock<std::mutex> lock(queue_mutex);

        //add task
        tasks.push_back(std::function<void()>(f));

}//release lock

为什么会比这个更受欢迎

queue_mutex.lock();

//add task
//...

queue_mutex.unlock();

这些sn-ps代码完成同样的事情吗?

【问题讨论】:

标签: c++ c++11 threadpool mutex stdthread


【解决方案1】:

[Do] 这些 sn-ps 代码完成同样的事情吗?

没有。

第一个将在块结束时释放锁,无论块是什么。如果临界区以breakcontinuereturngoto、异常或我忘记的任何其他类型的非本地跳转退出,则第二个不会在最后释放锁关于。

【讨论】:

  • 打败我!我还要补充一点,std::unique_lock 在 RAII 方面有很大的优势。假设互斥体中的方法在调用 unlock() 之前抛出。互斥锁可能永远不会解锁。即使抛出异常,std::unique_lock 也保证释放,因为 std::mutex 不会(因为必须手动调用解锁)。
  • IOW,第一个实际上做了大多数人在编写第二个时所希望的。
  • 那么在未来适用时始终选择使用std::unique_lock&lt;std::mutex&gt; 是否明智?
  • @SyntacticFructose 我会说是的。总而言之更安全一些。
  • @SyntacticFructose:在大多数情况下,一个简单的std::lock_guard 实际上就足够了。通常最好使用最简单的类型来完成某项任务。
【解决方案2】:

使用unique_lock 可以在面对变化和错误时提供弹性。

  • 如果您更改流程以添加中间“跳转”(例如return
  • 如果抛出异常
  • ...

在任何情况下,锁都会自动释放。

另一方面,如果您尝试手动操作,您可能会错过一个案例。即使您现在不这样做,以后的编辑也可能会。


注意:这是 C++ 中的一个常用习惯用法,称为 SBRM(范围绑定资源管理),您可以在其中绑定清理操作以展开堆栈,因此您可以放心,除非崩溃/非正常退出,否则它会被执行.

它还展示了 RAII(资源获取是初始化),因为 unique_lock 的构造本身就获取了资源(这里是互斥体)。尽管它的名字,这个首字母缩写词也通俗地用来指代销毁时的确定性释放,它比 SBRM 涵盖更广泛的范围,因为它指的是所有类型的确定性释放,而不仅仅是基于堆栈展开的那些.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-12
    • 2011-04-13
    • 1970-01-01
    • 2014-02-28
    • 2014-09-26
    相关资源
    最近更新 更多