博客
关于我
C++并发与多线程学习笔记--互斥量、用法、死锁概念
阅读量:459 次
发布时间:2019-03-06

本文共 2398 字,大约阅读时间需要 7 分钟。

互斥量与死锁的技术解析

互斥量的基本概念

互斥量(Mutex)是一种用于线程保护共享资源的机制。其核心思想是:当一个线程使用代码对共享数据加锁时,其他线程必须等待,直到当前线程释放锁才能继续操作。这是一种互斥访问的机制,防止数据竞态和并发错误。

互斥量的本质是一个类对象,代表一把锁。多线程之间通过调用lock()成员函数来竞争这把锁,只有一个线程能够成功加锁。如果某个线程在加锁过程中遇到阻力(例如已被占用的锁),它将卡在lock()函数那里,无法继续执行。这就是所谓的死锁现象。

互斥量的用法

在使用互斥量之前,需要包含相应的头文件:

#include 

lock()和unlock()

互斥量的基础操作是lock()和unlock()。线程在对共享数据进行操作之前,应该调用lock()加锁;操作完成后,必须调用unlock()释放锁。lock()和unlock()必须成对使用,不能出现不成对的情况。例如:

class ProcessRequest {private:    std::list
m_msgRecvQueue; std::mutex my_mutex; public: void inMsgRecvQueue() { for (int i = 0; i < 100000; ++i) { my_mutex.lock(); std::cout << "插入一个元素" << std::endl; m_msgRecvQueue.push_back(i); my_mutex.unlock(); } } bool outMsgLULProc(int &command) { if (!m_msgRecvQueue.empty()) { int command = m_msgRecvQueue.front(); m_msgRecvQueue.pop_front(); return true; } return false; } void outMsgRecvQueue() { int command = 0; for (int i = 0; i < 100000; ++i) { my_mutex.lock(); bool result = outMsgLULProc(command); if (result == true) { std::cout << "outMsgRecvQueue() 执行,取出一个元素" << std::endl; } else { std::cout << "outMsgRecvQueue() 还执行,但是消息队列为空" << std::endl; } my_mutex.unlock(); } }};

std::lock_guard的优势

为了避免开发者忘记释放锁,C++提供了std::lock_guard类模板。它在构造时自动调用Mutex::lock(),而在析构时自动调用Mutex::unlock()。因此,lock_guard可以直接替代传统的lock()和unlock(),使用更为方便和安全。

std::lock_guard的使用方式如下:

std::lock_guard
my_lock(my_mutex);// 加锁自动执行// ...// 解锁自动执行

注意:使用std::lock_guard后,不能再手动调用lock()或unlock(),这将导致错误。

死锁的概念

死锁是指两个或多个线程因占有互斥资源而阻塞,彼此无法继续执行的状态。死锁通常发生在多个线程竞争有限资源(如打印机和输入设备)时。例如:

  • 线程A占有金锁,试图锁定银锁。
  • 线程B占有银锁,试图锁定金锁。
  • 两个线程都无法继续执行,导致系统陷入僵局。

死锁的特征

  • 至少两个进程(线程)参与
  • 所有进程都在等待资源
  • 至少有两个进程占有资源
  • 死锁进程是系统当前进程的子集
  • 死锁会浪费系统资源,可能导致系统崩溃
  • 死锁的解决方案

    为了避免死锁,必须确保互斥锁的使用顺序一致。例如:

    Processor1:{    mutex1.lock();    mutex2.lock();    // ... 其他操作 ...    mutex1.unlock();    mutex2.unlock();}Processor2:{    mutex1.lock();    mutex2.lock();    // ... 其他操作 ...    mutex1.unlock();    mutex2.unlock();}

    std::lock函数模板

    在某些情况下,可能需要直接调用std::lock()函数模板来加锁:

    std::lock(&my_mutex);// 操作共享数据std::unlock(&my_mutex);

    std::lock_guard的std::adopt_lock参数

    std::lock_guard支持一个叫做std::adopt_lock的参数。它允许在构造函数外传入已经加锁的Mutex对象,这样不会重复加锁。这种方式可以提高性能,特别是在多级锁的情况下。

    参考文献

    你可能感兴趣的文章
    Python中信号处理程序和atexit处理程序的调用
    查看>>
    Python中关于txt的简单读写模式与操作
    查看>>
    Python中关于类和函数的初体验之"__init__"和"__str__"不是"_init_"和"_str_"
    查看>>
    python中函数接受参数为*args, **kwargs怎么办
    查看>>
    Python中切片的高效迭代
    查看>>
    python中列表乘法、eval、lambda、hasattr、assert、*(星)等的用法
    查看>>
    Python中制作词云的WordCloud参数详解
    查看>>
    Python中可用和使用的系统内存?
    查看>>
    python中存根文件(.pyi)的用途是什么?
    查看>>
    Python中实现ASCII码与字符相互转换
    查看>>
    Python中实现获取所有微信好友的头像并拼接成一张图片
    查看>>
    Python中对象的布尔值
    查看>>
    python中对集合的操作
    查看>>
    python中将列表转换为元组的时间复杂度,反之亦然
    查看>>
    Python中布尔表达式的求值
    查看>>
    python中很常用的10个内置函数整理(初学必备)
    查看>>
    python中打印二维列表数据
    查看>>
    python中打散数组shuffle
    查看>>
    Python中执行外部命令
    查看>>
    Python中拼接numpy数组-ChatGPT4o作答
    查看>>