C++之互斥锁、读写锁、互斥量、 信号量、原子锁机制总结(二百二十五)

2023-09-20 17:27:45

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!

优质专栏:Audio工程师进阶系列原创干货持续更新中……】🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

欢迎关注Android系统攻城狮

1.前言

本篇目的:C++之互斥锁、读写锁、互斥量、 信号量、原子锁机制用法.

互斥锁、读写锁、互斥量、信号量和原子锁都是并发编程中常用的同步机制。

  1. 互斥锁(Mutex Lock)是最常见的同步机制之一,它用于保护共享资源,只允许一个线程访问资源,其他线程需要等待。互斥锁有两种状态:加锁和解锁。当一个线程获得了互斥锁并执行代码时,其他线程会被阻塞,直到锁被释放。通过互斥锁可以避免多个线程同时访问共享资源而导致的数据竞争问题。

  2. 读写锁(Read-Write Lock)允许多个线程同时读取共享资源,但只有一个线程可以写入资源。读写锁在读取操作频繁、写入操作较少的场景下可以提高并发性能。当有线程正在写入资源时,其他线程无法读取或写入资源,读写锁会保持写锁的状态,直到写操作完成。

  3. 互斥量(Mutex)和互斥锁类似,也用于保护共享资源。互斥量是一种更通用的同步机制,可以实现更复杂的同步逻辑。与互斥锁不同的是,互斥量可以由多个线程共享。

  4. 信号量(Semaphore)是一种计数器,用于控制对共享资源的访问。它可以控制同时访问资源的线程数量,并提供了同步和互斥的机制。信号量有两种操作:P操作(等待)和V操作(释放)。当信号量的计数器为0时,执行P操作的线程会被阻塞,直到计数器大于0时才能继续执行。

  5. 原子锁(Atomic Lock)是一种基于原子操作的同步机制,用于保护对共享资源的访问。原子操作是指不会被其他线程中断的操作。原子锁能够确保在同一时刻只有一个线程可以执行临界区代码,从而避免了竞态条件的发生。

2.应用实例

<1>. 互斥锁(Mutex Lock)的作用是保护共享资源,确保在同一时间只有一个线程可以访问该资源。

#include <iostream>
#include <mutex>

std::mutex mtx;

void sharedResourceAccess() {
    // 锁定互斥锁,确保只有一个线程可以进入临界区
    mtx.lock();

    // 访问共享资源的代码
    // ...

    // 解锁互斥锁,允许其他线程访问共享资源
    mtx.unlock();
}

int main() {
    // 创建多个线程并发访问共享资源
    // ...

    return 0;
}

<2>. 读写锁(Read-Write Lock)的作用是允许多个线程同时读取共享资源,但只有一个线程可以写入资源。

#include <iostream>
#include <shared_mutex>

std::shared_mutex rwMutex;

void readAccess() {
    // 读操作,可以同时由多个线程进入临界区
    std::shared_lock<std::shared_mutex> readLock(rwMutex);

    // 读取共享资源的代码
    // ...
}

void writeAccess() {
    // 写操作,只有一个线程可以进入临界区
    std::unique_lock<std::shared_mutex> writeLock(rwMutex);

    // 写入共享资源的代码
    // ...
}

int main() {
    // 创建多个线程并发读写共享资源
    // ...

    return 0;
}

<3>. 互斥量(Mutex)的作用与互斥锁类似,也用于保护共享资源。互斥量可以由多个线程共享,其用法与互斥锁类似。

#include <iostream>
#include <mutex>

std::mutex mtx;

void sharedResourceAccess() {
    // 锁定互斥量,确保只有一个线程可以进入临界区
    std::lock_guard<std::mutex> lock(mtx);

    // 访问共享资源的代码
    // ...
}

int main() {
    // 创建多个线程并发访问共享资源
    // ...

    return 0;
}

<4>. 信号量(Semaphore)的作用是控制对共享资源的访问,限制同时访问资源的线程数量。

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

std::mutex mtx;
std::condition_variable cv;
int counter = 0;

void accessResource() {
    std::unique_lock<std::mutex> lock(mtx);

    // 等待信号量,当 counter 大于 0 时继续执行
    cv.wait(lock, [] { return counter > 0; });

    // 访问共享资源的代码
    // ...

    // 释放信号量,计数器减一
    counter--;
}

void releaseResource() {
    std::unique_lock<std::mutex> lock(mtx);

    // 增加信号量,计数器加一
    counter++;

    // 通知等待的线程可以继续执行
    cv.notify_one();
}

int main() {
    // 创建多个线程并发访问共享资源
    // ...

    return 0;
}

<5>.原子锁,用于保护对共享资源的访问,原子操作是指不会被其他线程中断的操作。

#include <iostream>
#include <atomic>
#include <thread>

// 创建一个原子锁
std::atomic<bool> atomic_lock(false);

void criticalSection() {
    while (atomic_lock.exchange(true)) {
        // 原子锁正在被其他线程使用,等待...
    }

    // 进入临界区,访问共享资源
    std::cout << "进入临界区,访问共享资源" << std::endl;

    // 模拟一段临界区代码
    std::this_thread::sleep_for(std::chrono::seconds(2));

    // 退出临界区,释放原子锁
    atomic_lock.store(false);
    std::cout << "退出临界区,释放原子锁" << std::endl;
}

int main() {
    // 创建多个线程并发访问临界区
    std::thread t1(criticalSection);
    std::thread t2(criticalSection);

    // 等待线程完成
    t1.join();
    t2.join();

    return 0;
}

3.自定义实现Mutex自动加锁和解锁

#include <iostream>
#include <mutex>

class Mutex {
public:
  void lock() {
    // 实现互斥锁的加锁操作
    std::cout << "Mutex locked" << std::endl;
  }

  void unlock() {
    // 实现互斥锁的解锁操作
    std::cout << "Mutex unlocked" << std::endl;
  }
};

class Autolock {
public:
  explicit Autolock(Mutex& mutex) : mLock(mutex) {
    mLock.lock();
  }

  ~Autolock() {
    mLock.unlock();
  }

private:
  Mutex& mLock;
};

int main() {
  Mutex mutex;
  {
    Autolock autolock(mutex);  // 创建Autolock对象,自动加锁
    // 执行在临界区内的操作
    std::cout << "In critical section" << std::endl;
  }  // Autolock对象销毁,自动解锁

  return 0;
}

```
`注意:使用构造函数和析构函数实现Mutex自动加锁和解锁。`
更多推荐

【JavaSE专栏49】Java集合类LinkedList解析,链表和顺序表有什么不同?

作者主页:Designer小郑作者简介:3年JAVA全栈开发经验,专注JAVA技术、系统定制、远程指导,致力于企业数字化转型,CSDN学院、蓝桥云课认证讲师。主打方向:Vue、SpringBoot、微信小程序本文讲解了Java中集合类LinkedList的语法、使用说明和应用场景,并给出了样例代码。目录一、什么是Lin

[C++入门]---List的使用及模拟实现

文章目录1.list的介绍2.list的使用2.1list的构造函数2.2listmodifiers2.3listcapacity2.4listelmentaccess2.5iterator的使用3.list的模拟实现3.1list的源码1.list的介绍list是可以在常数范围内在任意位置进行插入和删除的序列式容器,

【Java 基础篇】深入理解Java HashMap:使用注意事项和性能优化

Java是一种广泛使用的编程语言,而集合是Java编程中不可或缺的一部分。在Java的集合框架中,HashMap是一个常用的数据结构,用于存储键值对。本文将深入介绍HashMap集合,从基础到高级用法,帮助您更好地理解和利用它。什么是HashMap?HashMap是Java集合框架中的一个类,它实现了Map接口,用于存

求生之路2服务器搭建插件安装及详细的游戏参数配置教程windows

求生之路2服务器搭建插件安装及详细的游戏参数配置教程windows大家好我是艾西,最近研究了下l4d2(求生之路2)这款游戏的搭建以及架设过程。今天就给喜欢l4d2这款游戏的小伙伴们分享下怎么搭建架设一个自己的服务器。毕竟自己当服主是热爱游戏每一个人的梦想,在自己的服务器里为所欲为在游戏里成就自己。(注:因PT原因本文

RocketMQ消息的分类

一、普通消息1消息发送分类Producer对于消息的发送方式也有多种选择,不同的方式会产生不同的系统效果。同步发送消息同步发送消息是指,Producer发出⼀条消息后,会在收到MQ返回的ACK之后才发下⼀条消息。该方式的消息可靠性最高,但消息发送效率太低。异步发送消息异步发送消息是指,Producer发出消息后无需等待

【Jetpack】Navigation 导航组件 ④ ( Fragment 跳转中使用 safe args 安全传递参数 )

文章目录一、页面跳转间的传统的数据传递方式1、传统的数据传递方式-Bundle传递数据1、Navigation组件中的Bundle数据传递2、传统数据传递实现步骤3、FragmentA完整代码示例4、FragmentB完整代码示例5、执行结果2、使用Bundle传递数据安全性差二、页面跳转间的传统的数据传递方式1、导入

C++--哈希表的实现及unorder_set和unorder_map的封装

1.什么是哈希表哈希表是一种数据结构,用来存放数据的,哈希表存放的数据是无序的,可以实现增删查,当时不能修改数据。可以不经过任何比较,一次直接从表中得到要搜索的元素。如果构造一种存储结构,通过某种函数(hashFunc)使元素的存储位置与它的关键码之间能够建立一一映射的关系,那么在查找时通过该函数可以很快找到该元素。该

知乎万赞的:网络安全系统自学就业路线,建议收藏!

为什么说网络安全是新风口?近几年,随着移动互联网、大数据、云计算、人工智能等新一代信息技术的快速发展,围绕网络和数据的服务与应用呈现爆发式增长,丰富的应用场景下暴露出越来越多的网络安全风险和问题。但是,我国网络安全整体投入不高。网络安全建设方面,国内网络安全投入占信息化的投入比例大概不到百分之3%,而欧美等发达国家均在

Python 超高频常见字符操作【建议收藏】

文章目录前言1.字符串截取2.字符串拼接3.字符串搜索4.字符串格式化5.字符串替换6.字符串去除空格7.字符串截取8.字符串反转总结前言为了巩固所学的知识,作者尝试着开始发布一些学习笔记类的博客,方便日后回顾。当然,如果能帮到一些萌新进行新技术的学习那也是极好的。作者菜菜一枚,文章中如果有记录错误,欢迎读者朋友们批评

A Survey of Hallucination in “Large” Foundation Models

本文是LLM系列文章,针对《ASurveyofHallucinationin“Large”FoundationModels》的翻译。大型基础模型幻觉现象综述摘要1引言2大语言模型中的幻觉3大图像模型中的幻觉4大视频模型中的幻觉5大音频模型中的幻觉6幻觉不总是有害的:不同的视角7结论和未来方向7.1幻觉的自动评估7.2利

解密堆排序与TopK问题

📙作者简介:清水加冰,目前大二在读,正在学习C/C++、Python、操作系统、数据库等。📘相关专栏:C语言初阶、C语言进阶、C语言刷题训练营、数据结构刷题训练营、有感兴趣的可以看一看。欢迎点赞👍收藏⭐留言📝如有错误还望各路大佬指正!✨每一次努力都是一种收获,每一次坚持都是一种成长✨目录前言1.堆排序1.1时间

热文推荐