C++11特性:std::lock_guard是否会引起死锁?

本文探讨了C++中使用lock_guard进行线程同步的优点,如RAII自动管理、异常安全和避免死锁,同时比较了lock_guard与unique_lock的差异,以及如何在实际场景中避免潜在的死锁问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天在评审代码的时候,因为位于两个不同的线程中(一个是周期性事件线程,一个是触发式事件线程),需要对一个资源类的某些属性进行互斥的访问,因此采用lock_guard互斥量包装器,但是在升级的过程中,因为整个系统太大,所以在询问了某位同事后,得到的答案是在两个不同的地方加上lock_guard有一定的可能性会导致死锁,但是后面在测试的过程中又没有问题,真的如此吗?本文针对lock_guard来做阐述和延申

历史原因:为什么要使用lock_gurad,有什么优点

传统的C++对互斥量加锁是用互斥量本身的锁的,即

#include <mutex>

std::mutex g_mutex;

// 加锁
g_mutex.lock();
// 解锁
g_mutex.unlock();

此时会有两个不便利处,即要手动的解锁,如果忘了解锁,那就完蛋了!,因此采用lock_guard

#include <mutex>

std::mutex g_mutex;

{
    // 作用域开始
 	std::lock_guard<std::mutex> lock(g_mutex);
} // 作用域结束

lock_guard以作用域为加解锁单位,退出当前作用域自动解锁,不必手动解锁。总结一下它的优点

  • RAII(资源获取即初始化)语法:std::lock_guard 使用对象的构造函数和析构函数来自动管理互斥量的锁定和解锁,从而避免了手动管理锁的复杂性。这种自动化的资源管理方式确保在作用域结束时释放锁,防止忘记解锁而导致的资源泄漏或死锁
  • 异常安全:由于 std::lock_guard 使用RAII语法,即使在作用域内发生异常,也会自动调用析构函数释放锁,确保了异常安全性。这样可以避免在异常发生时锁没有被释放而导致的资源泄漏或死锁
  • 简单易用:std::lock_guard 提供了一种简单而直观的方式来管理互斥量,不需要手动调用 lock() unlock() 函数,因此代码更加简洁清晰,易于理解和维护
  • 避免死锁:由于 std::lock_guard 在构造时立即锁定互斥量,在析构时立即释放互斥量,因此减少了出现死锁的可能性。通过使用 std::lock_guard,程序员可以更容易地确保正确的加锁和解锁顺序,从而避免死锁
  • 线程安全性:std::lock_guard 是线程安全的,可以在多线程环境下安全地使用。它能够确保在同一时间只有一个线程可以访问被互斥量保护的资源,从而保证了线程安全性

lock_guard和unique_lock的区别

延迟加锁:可以在构造时不立即锁定互斥量,在需要时手动调用 lock() 函数来锁定互斥量。这种延迟加锁的特性允许在一段代码中多次锁定和解锁互斥量,提供了更多的灵活性

void FunThread()
{
   
	std::unique_lock<std::mutex> lock(mtx, std::defer_lock); // 延迟加锁,此时不加锁
	
	lock.lock(); // 加锁
	//
	lock.unlock(); // 解锁
}

条件等待:提供了与条件变量一起使用的功能,可以在条件变量的等待和通知过程中自动锁定和解锁互斥量。通过将 std::unique_lock 对象传递给条件变量的wait()notify_*() 函数,可以轻松实现条件等待的功能

配合条件变量使用的时候必须使用unique_lock,因此lock_guard不会自动释放锁,试想,在wait之前,本线程已经持有锁了,在等待的时候,如果一直持有互斥量,那其他线程也会拿不到互斥量,执行不了逻辑,则会导致永久死锁,可见源码

    template <class _Lock, class _Predicate>
    bool wait(_Lock& __lock,
              stop_token __stoken,
              _Predicate __p)
    {
   
      if (__stoken.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

妖怪喜欢风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值