博客
关于我
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对象,这样不会重复加锁。这种方式可以提高性能,特别是在多级锁的情况下。

    参考文献

    你可能感兴趣的文章
    Objective-C实现isalpha函数功能(附完整源码)
    查看>>
    Objective-C实现islower函数功能(附完整源码)
    查看>>
    Objective-C实现isPowerOfTwo算法(附完整源码)
    查看>>
    Objective-C实现isupper函数功能(附完整源码)
    查看>>
    Objective-C实现ItemCF算法(附完整源码)
    查看>>
    Objective-C实现ItemCF算法(附完整源码)
    查看>>
    Objective-C实现iterating through submasks遍历子掩码算法(附完整源码)
    查看>>
    Objective-C实现iterative merge sort迭代归并排序算法(附完整源码)
    查看>>
    Objective-C实现jaccard similarity相似度无平方因子数算法(附完整源码)
    查看>>
    Objective-C实现Julia集算法(附完整源码)
    查看>>
    Objective-C实现k nearest neighbours k最近邻分类算法(附完整源码)
    查看>>
    Objective-C实现k-Means算法(附完整源码)
    查看>>
    Objective-C实现k-nearest算法(附完整源码)
    查看>>
    Objective-C实现KadaneAlgo计算给定数组的最大连续子数组和算法(附完整源码)
    查看>>
    Objective-C实现karatsuba大数相乘算法(附完整源码)
    查看>>
    Objective-C实现KMP搜索算法(附完整源码)
    查看>>
    Objective-C实现Knapsack problem背包问题算法(附完整源码)
    查看>>
    Objective-C实现knapsack背包问题算法(附完整源码)
    查看>>
    Objective-C实现knapsack背包问题算法(附完整源码)
    查看>>
    Objective-C实现knight tour骑士之旅算法(附完整源码)
    查看>>