std::mutex 锁定函数和 std::lock_guard<std::mutex> 的区别?

Posted

技术标签:

【中文标题】std::mutex 锁定函数和 std::lock_guard<std::mutex> 的区别?【英文标题】:Difference between std::mutex lock function and std::lock_guard<std::mutex>? 【发布时间】:2016-07-12 23:28:12 【问题描述】:

基本上,标题是不言自明的。 我以以下方式使用它:

代码在 Objective-C++ 中。 Objective-C 类对不同用途的函数进行并发调用。 我在整个类中使用 std::mutexlockunlock std::vector&lt;T&gt; 编辑选项,因为 C++ 标准容器不是线程安全的。

【问题讨论】:

【参考方案1】:

使用lock_guard 会在互斥锁超出范围时自动再次解锁。这使得在返回或抛出异常时不可能忘记解锁它。您应该始终更喜欢使用lock_guardunique_lock 而不是mutex::lock()。见http://kayari.org/cxx/antipatterns.html#locking-mutex

lock_guard 是 RAII 或 SBRM 类型的示例。

【讨论】:

【参考方案2】:

std::lock_guard 仅用于两个目的:

    在销毁期间自动解锁互斥锁(无需致电.unlock())。 允许同时锁定多个互斥锁以克服死锁问题。

对于最后一个用例,您需要std::adopt_lock 标志:

std::lock(mutex_one, mutex_two);
std::lock_guard<std::mutex> lockPurposeOne(mutex_one, std::adopt_lock);
std::lock_guard<std::mutex> lockPurposeTwo(mutex_two, std::adopt_lock);

另一方面,每次需要锁定互斥锁时,都需要为守卫分配另一个类实例,因为std::lock_guard 没有成员函数。如果您需要具有解锁功能的防护,请查看std::unique_lock 类。您也可以考虑使用std::shared_lock 来并行读取您的向量。

您可能会注意到,std::shared_lock 类在头文件中被注释并且只能使用 C++17 访问。根据头文件,你可以使用std::shared_timed_mutex,但是当你尝试构建应用程序时它会失败,因为Apple更新了头文件,而不是libc++本身。

因此,对于 Objective-C 应用程序,使用 GCD 可能更方便,同时为所有 C++ 容器分配几个队列,并在需要的地方放置信号量。看看这个出色的comparison。

【讨论】:

"每次你需要锁定互斥锁时,你需要为守卫分配另一个类实例"是什么意思?你让lock_guard听起来很糟糕。 如果你需要它也不错。但是,如果您以这种方式构建应用程序,则不会出现这种死锁——您不需要它。

以上是关于std::mutex 锁定函数和 std::lock_guard<std::mutex> 的区别?的主要内容,如果未能解决你的问题,请参考以下文章

查询 std::mutex 的锁定状态

使用 boost strand 和 std::mutex

在不同的函数中锁定/解锁 std::unique_lock

std::mutex 如何在不同的线程中解锁?

为啥 OSX 上的 std::mutex 这么慢?

c++ 如何将 std::mutex 和 std::lock_guard 与仿函数一起使用?