C++:线程当中的锁专题

在 C++ 多线程编程中,线程同步是确保程序正确运行的关键环节,而锁机制则是实现线程同步的重要手段。

一、线程的同步之互斥锁

1.1 互斥锁的概念

互斥锁(Mutex,即 Mutual Exclusion 的缩写)是一种最基本的线程同步工具,用于保证在同一时刻只有一个线程能够访问共享资源,从而避免数据竞争和不一致的问题。其工作原理就像一个房间的钥匙,同一时间只有拿到钥匙的线程才能进入房间(访问共享资源),其他线程必须等待钥匙被释放后才能尝试获取。

1.2 互斥锁的使用场景

当多个线程需要访问和修改共享数据,且这些操作不是原子操作时,就需要使用互斥锁来保护共享数据。例如,在一个多线程的银行账户管理系统中,多个线程可能同时对账户余额进行取款和存款操作,如果不加以同步,就可能导致账户余额出现错误。

1.3 互斥锁的使用方法

在 C++ 中,使用头文件来操作互斥锁。

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

std::mutex mtx;
int sharedData = 0;

void increment() {
    mtx.lock();
    sharedData++;
    mtx.unlock();
}

int main() {
    std::thread threads[10];
    for (int i = 0; i < 10; ++i) {
        threads[i] = std::thread(increment);
    }

    for (auto& th : threads) {
        th.join();
    }

    std::cout << "Final value of sharedData: " << sharedData << std::endl;
    return 0;
}

std::thread threads[10];:定义了一个包含 10 个 std::thread 对象的数组 threads,用于存储创建的线程。
for (int i = 0; i < 10; ++i) { threads[i] = std::thread(increment); }:使用 for 循环创建 10 个线程,每个线程都执行 increment 函数。std::thread(increment) 会启动一个新线程并将 increment 函数作为线程的执行体。
for (auto& th : threads) { th.join(); }:使用范围 for 循环遍历 threads 数组,调用每个线程的 join 方法。join 方法会阻塞主线程,直到对应的子线程执行完毕。这样可以确保主线程在所有子线程执行完毕后再继续执行后续代码。

std::mutex mtx定义了一个互斥锁,increment函数在访问和修改sharedData之前,先通过mtx.lock()获取锁,操作完成后通过mtx.unlock()释放锁,确保了同一时间只有一个线程能修改sharedData。

二、读写锁

2.1 读写锁的概念

读写锁(Read-Write Lock)是一种特殊的同步机制,它区分了读操作和写操作。允许多个线程同时进行读操作,因为读操作不会修改共享数据,不会产生数据竞争;但只允许一个线程进行写操作,并且在写操作时不允许其他线程进行读或写操作,以保证数据的一致性。

2.2 读写锁的使用场景

当共享资源的读操作远远多于写操作时,使用读写锁可以显著提高程序的性能。例如,在一个多线程的数据库查询系统中,大量线程可能同时进行数据查询(读操作),而只有少数线程会进行数据更新(写操作)。

2.3 读写锁的使用方法

在 C++ 中,可以使用<shared_mutex>头文件来操作读写锁。

#include <iostream>
#include <shared_mutex>
#include <thread>

std::shared_mutex rwMutex;
int sharedValue = 0;

void read() {
    rwMutex.lock_shared();
    std::cout << "Reading value: " << sharedValue << std::endl;
    rwMutex.unlock_shared();
}

void write() {
    rwMutex.lock();
    sharedValue++;
    std::cout << "Writing value: " << sharedValue << std::endl;
    rwMutex.unlock();
}

int main() {
    std::thread readThreads[5];
    std::thread writeThread(write);

    for (int i = 0; i < 5; ++i) {
        readThreads[i] = std::thread(read);
    }

    for (auto& th : readThreads) {
        th.join();
    }

    writeThread.join();
    return 0;
}

std::shared_mutex rwMutex定义了一个读写锁。read函数使用lock_shared进行读锁定,允许多个线程同时读;write函数使用lock进行写锁定,确保同一时间只有一个线程能写。

三、互斥锁非阻塞式锁

3.1 非阻塞式锁的概念

非阻塞式锁是指线程在尝试获取锁时,如果锁当前被其他线程占用,不会阻塞等待,而是立即返回一个状态值,告知线程获取锁的结果,线程可以根据这个结果决定后续的操作。

3.2 非阻塞式锁的使用场景

在一些对响应时间要求较高,且线程不能长时间阻塞的场景中,非阻塞式锁非常有用。例如,在一个实时性要求较高的图形界面应用中,线程需要快速响应用户的操作,不能因为等待锁而导致界面卡顿。

3.3 非阻塞式锁的使用方法

在 C++ 中,std::mutex提供了try_lock方法来实现非阻塞式加锁。

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

std::mutex mtx;
int sharedResource = 0;

void attemptAccess() {
    if (mtx.try_lock()) {
        std::cout << "Thread got the lock." << std::endl;
        sharedResource++;
        mtx.unlock();
    } else {
        std::cout << "Thread couldn't get the lock." << std::endl;
    }
}

int main() {
    std::thread threads[3];
    for (int i = 0; i < 3; ++i) {
        threads[i] = std::thread(attemptAccess);
    }

    for (auto& th : threads) {
        th.join();
    }

    return 0;
}

attemptAccess函数使用try_lock尝试获取锁,如果获取成功则进行操作,否则直接返回。

四、读写锁非阻塞式上锁

4.1 读写锁非阻塞式上锁的概念

与互斥锁的非阻塞式上锁类似,读写锁的非阻塞式上锁允许线程在尝试获取读锁或写锁时,如果锁被占用,不会阻塞等待,而是立即返回结果,以便线程灵活处理。

4.2 读写锁非阻塞式上锁的使用场景

在一些需要快速响应,且读操作和写操作都不能长时间阻塞的场景中适用。比如在一个高速缓存系统中,线程需要快速判断能否获取锁来进行数据的读取或更新,而不是一直等待锁的释放。

4.3 读写锁非阻塞式上锁的使用方法

在 C++ 中,std::shared_mutex提供了try_lock_shared和try_lock方法来实现非阻塞式的读锁和写锁获取

#include <iostream>
#include <shared_mutex>
#include <thread>

std::shared_mutex rwMutex;
int sharedData = 0;

void tryRead() {
    if (rwMutex.try_lock_shared()) {
        std::cout << "Thread got read lock. Data: " << sharedData << std::endl;
        rwMutex.unlock_shared();
    } else {
        std::cout << "Thread couldn't get read lock." << std::endl;
    }
}

void tryWrite() {
    if (rwMutex.try_lock()) {
        sharedData++;
        std::cout << "Thread got write lock. Data updated: " << sharedData << std::endl;
        rwMutex.unlock();
    } else {
        std::cout << "Thread couldn't get write lock." << std::endl;
    }
}

int main() {
    std::thread readThreads[3];
    std::thread writeThread(tryWrite);

    for (int i = 0; i < 3; ++i) {
        readThreads[i] = std::thread(tryRead);
    }

    for (auto& th : readThreads) {
        th.join();
    }

    writeThread.join();
    return 0;
}

tryRead函数使用try_lock_shared尝试获取读锁,tryWrite函数使用try_lock尝试获取写锁,根据获取结果进行相应操作。

线程同步中的各类锁机制是 C++ 多线程编程的重要组成部分。互斥锁用于基本的线程同步,读写锁适用于读多写少的场景,非阻塞式锁则为需要快速响应的场景提供了解决方案。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/973611.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【排版教程】如何在Word/WPS中优雅的插入参考文献

材料展示 随便选取一段综述内容&#xff0c;以及对应的参考文献&#xff0c;如下图所示&#xff1a; 1 参考文献编辑 首先对参考文献部分进行编辑&#xff0c;将其设置自动编号 在段落中&#xff0c;选择悬挂缩进 在编号中&#xff0c;设置自定义编号&#xff0c;然后按照…

STM32 看门狗

目录 背景 独立看门狗&#xff08;IWDG&#xff09; 寄存器访问保护 窗口看门狗&#xff08;WWDG&#xff09; 程序 独立看门狗 设置独立看门狗程序 第一步、使能对独立看门狗寄存器的写操作 第二步、设置预分频和重装载值 第三步、喂狗 第四步、使能独立看门狗 喂狗…

【第二节】C++设计模式(创建型模式)-抽象工厂模式

目录 引言 一、抽象工厂模式概述 二、抽象工厂模式的应用 三、抽象工厂模式的适用场景 四、抽象工厂模式的优缺点 五、总结 引言 抽象工厂设计模式是一种创建型设计模式&#xff0c;旨在解决一系列相互依赖对象的创建问题。它与工厂方法模式密切相关&#xff0c;但在应用…

docker基操

docker基操 首先就是安装docker使用docker:创建容器-制作一个镜像-加载镜像首先就是安装docker 随便找一个教程安装就可以,安装过程中主要是不能访问谷歌,下面这篇文章写了镜像的一些问题: 安装docker的网络问题 使用docker:创建容器-制作一个镜像-加载镜像 主要是参考:这篇…

3D打印注塑件-省模具费90%的解决方案

"开模费用50万&#xff0c;首批订单才200件&#xff1f;" 这是许多制造企业的真实困境。传统注塑工艺动辄数周的开模周期和5-50万元的模具成本&#xff0c;让中小企业的产品迭代举步维艰。 在传统制造流程中&#xff0c;注塑件的生产往往需要高昂的模具开发费用和较…

Java+SpringBoot+Vue+数据可视化的综合健身管理平台(程序+论文+讲解+安装+调试+售后)

感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;我会一一回复&#xff0c;希望帮助更多的人。 系统介绍 在当今社会&#xff0c;随着人们生活水平的不断提高和健康意识的日益增强&#xff0c;健…

美的楼宇科技基于阿里云 EMR Serverless Spark 构建 LakeHouse 湖仓数据平台

作者&#xff1a;美的楼宇科技事业部 先行研究中心智能技术部 美的楼宇科技 IoT 数据平台建设背景 美的楼宇科技事业部&#xff08;以下简称楼宇科技&#xff09;是美的集团旗下五大板块之一&#xff0c;产品覆盖多联机组、大型冷水机组、单元机、机房空调、扶梯、直梯、货梯…

matlab 车辆进出检测算法设计GUI界面-论文

1、内容简介 matlab151-车辆进出检测算法设计GUI界面-论文 可以交流、咨询、答疑 2、内容说明 略 随着科学技术的进步&#xff0c;社会的发展&#xff0c;各行各业都在发生着巨大的变化。近段时间以来&#xff0c;“无人化”智能产业正处于一个风口阶段&#xff0c;似乎我们…

python学习书籍推荐

### Python 学习路线图概述 为了有效地掌握Python这门编程语言并应用于不同领域&#xff0c;构建一个合理的学习路径至关重要。此学习路径不仅涵盖了基础语法&#xff0c;还深入到特定应用方向的关键技术。 #### 基础阶段 在这个初始阶段&#xff0c;重点在于理解Python的基…

基于Spring Boot的农事管理系统设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

在 Ansys Motion 中创建链式伸缩臂的分步指南

介绍 链传动在负载和/或运动要远距离传递的机器中非常多产&#xff0c;例如&#xff0c;在两个平行轴之间。链条驱动系统的设计需要了解载荷传递和运动学如何影响链条张力、轴轴承中的悬臂载荷、轴应力和运动质量等。使用 Ansys Motion&#xff0c;可以轻松回答上述所有问题以…

Web Scraper,强大的浏览器爬虫插件!

Web Scraper是一款功能丰富的浏览器扩展爬虫工具&#xff0c;有着直观的图形界面&#xff0c;无需编写代码即可自定义数据抓取规则&#xff0c;高效地从网页中提取结构化数据&#xff0c;而且它支持灵活的数据导出选项&#xff0c;广泛应用于电商监控、内容聚合、市场调研等多元…

数据结构:栈和队列详解(下)

目录 一.如何用队列实现栈 1.思路&#xff1a; 2.具体代码&#xff1a; 二.如何用栈实现队列 1.思路&#xff1a; 2.具体代码&#xff1a; 一.如何用队列实现栈 原题来源&#xff1a;https://leetcode.cn/problems/implement-stack-using-queues/description/ 前言&#xf…

DeepSeek智能测试知识库助手PRO版:多格式支持+性能优化

前言 测试工程师在管理测试资产时,需要面对多种文档格式、大量文件分类及知识库的构建任务。为了解决这些问题,我们升级了 DeepSeek智能测试知识库助手,不仅支持更多文档格式,还加入了 多线程并发处理 和 可扩展格式支持,大幅提升处理性能和灵活性。 主要功能亮点: 多格…

宝塔面板开始ssl后,使用域名访问不了后台管理

宝塔面板后台开启ssl访问后&#xff0c;用的证书是其他第三方颁发的证书 再使用 域名/xxx 的形式&#xff1a;https://域名:xxx/xxx 访问后台&#xff0c;结果出现如下&#xff0c;不管使用 http 还是 https 的路径访问都进不后台管理 这个时候可以使用 https://ip/xxx 的方式来…

机器学习_12 逻辑回归知识点总结

逻辑回归是机器学习中一种重要的分类算法&#xff0c;广泛应用于二分类和多分类问题。它不仅能够预测分类结果&#xff0c;还能提供每个类别的概率估计。今天&#xff0c;我们就来深入探讨逻辑回归的原理、实现和应用。 一、逻辑回归的基本概念 1.1 逻辑回归与线性回归的区别…

AI Agent实战:打造京东广告主的超级助手 | 京东零售技术实践

前言 自2022年末ChatGPT的问世&#xff0c;大语言模型&#xff08;LLM&#xff09;技术引发全球关注。在大模型技术落地的最佳实践中&#xff0c;智能体&#xff08;Agent&#xff09;架构显现出巨大潜力&#xff0c;成为业界的普遍共识&#xff0c;各大公司也纷纷启动Agent技…

【工具篇】【深度解析 DeepAI 工具:开启 AI 应用新体验】

一、DeepAI 基本信息 嘿,咱先来说说 DeepAI 这工具到底是啥。DeepAI 是一个综合性的人工智能平台,就像是一个装满各种 AI 魔法的百宝箱。它把好多先进的人工智能技术整合到一起,让咱们普通人也能轻松用上这些高大上的 AI 功能。 这个平台背后有一群超厉害的技术人员,他们…

C语言之typedef

目录 前言 一、基本数据类型定义 二、作用 自带阅读 封装复杂类型的描述过程 三、指针类型定义 ​ 四、函数类型定义 总结 前言 typedef是C语言中用来为已有数据类型取别名的关键字。通过使用typedef关键字&#xff0c;可以方便地为数据类型定义新的名称&#xff0c;提高代码的…

如何在 SpringBoot 项目使用 Redis 的 Pipeline 功能

本文是博主在批量存储聊天中用户状态和登陆信息到 Redis 缓存中时&#xff0c;使用到了 Pipeline 功能&#xff0c;并对此做出了整理。 一、Redis Pipeline 是什么 Redis 的 Pipeline 功能可以显著提升 Redis 操作的性能&#xff0c;性能提升的原因在于可以批量执行命令。当我…