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

news2025/2/22 18:39:58

在 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++ 多线程编程的重要组成部分。互斥锁用于基本的线程同步,读写锁适用于读多写少的场景,非阻塞式锁则为需要快速响应的场景提供了解决方案。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Frp部署文档

Frp部署文档 开源项目地址:https://github.com/fatedier/frp项目中文文档地址&#xff1a;https://github.com/fatedier/frp/blob/dev/README_zh.md官网文档地址: https://gofrp.org/zh-cn/docs/发布包地址&#xff1a;https://github.com/fatedier/frp/releases 要注意对应的…

创建一个简单的spring boot+vue前后端分离项目

一、环境准备 此次实验需要的环境&#xff1a; jdk、maven、nvm和node.js 开发工具&#xff1a;idea或者Spring Tool Suite 4&#xff0c;前端可使用HBuilder X&#xff0c;数据库Mysql 下面提供maven安装与配置步骤和nvm安装与配置步骤&#xff1a; 1、maven安装与配置 1…

Spring Boot项目@Cacheable注解的使用

Cacheable 是 Spring 框架中用于缓存的注解之一&#xff0c;它可以帮助你轻松地将方法的结果缓存起来&#xff0c;从而提高应用的性能。下面详细介绍如何使用 Cacheable 注解以及相关的配置和注意事项。 1. 基本用法 1.1 添加依赖 首先&#xff0c;确保你的项目中包含了 Spr…

124.二叉树中的最大路径和 python

二叉树中的最大路径和 题目题目描述示例 1&#xff1a;示例 2&#xff1a;提示&#xff1a; 题解解决方案步骤Python 实现解释提交结果 题目 题目描述 二叉树中的 路径 被定义为一条节点序列&#xff0c;序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多…

23.1 WebBrowser控件

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 WebBrowser控件类似于IE浏览器的文档界面&#xff08;事实上IE也是使用的这个控件&#xff09;&#xff0c;它提供了显示网页及支持…

vue 手写分页

【先看效果】 &#xff08;1&#xff09;内容小于2页 不展示页码 &#xff08;2&#xff09;1 < 内容页数< 限定展示页码 展示&#xff1a;页码、上下页&#xff1b;隐藏&#xff1a;首页、末页图标&#xff0c;上、下一区间码。即&#xff1a;&#xff08;页数&#…

位运算,双指针,二分,排序算法

文章目录 位运算二进制中1的个数题解代码我们需要0题解代码 排序模版排序1题解代码模版排序2题解代码模版排序3题解代码 双指针最长连续不重复子序列题解代码 二分查找题解代码 位运算 1. bitset< 16 >将十进制数转为16位的二进制数 int x 25; cout << bitset<…

Typora软件(Markdown编辑器)详细安装教程(附补丁包)2025最详细图文教程安装手册

目录 前言&#xff1a;Typora是干什么的&#xff1f; 一、下载Typora安装包 二、安装Typora 1.运行安装程序 2.启动安装 3.创建桌面图标 4.开始安装 5.安装完成 三、安装补丁 1.解压补丁包 2.在解压后的补丁包目录下找到“winmm.dll” 3.复制“winmm.dll”到Typora安…

图谱洞见:专栏概要与内容目录

文章目录 图谱洞见&#x1f4da; 核心内容模块时空图模型研究综述与模型对比交通流量预测 知识图谱理论研究预训练语言模型与知识图谱知识图谱补全与链接预测知识蒸馏与知识表示关系建模与图卷积上下文感知与参数生成规则学习与推理可解释性研究因果推理 知识图谱实践应用数据库…

【拜读】Tensor Product Attention Is All You Need姚期智团队开源TPA兼容RoPE位置编码

姚期智团队开源新型注意力&#xff1a;张量积注意力&#xff08;Tensor Product Attention&#xff0c;TPA&#xff09;。有点像一种「动态的LoRA」&#xff0c;核心思路在于利用张量分解来压缩注意力机制中的 Q、K、V 表示&#xff0c;同时保留上下文信息&#xff0c;减少内存…

【电机控制器】ESP32-C3语言模型——DeepSeek

【电机控制器】ESP32-C3语言模型——DeepSeek 文章目录 [TOC](文章目录) 前言一、简介二、代码三、实验结果四、参考资料总结 前言 使用工具&#xff1a; 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、简介 二、代码 #include <Arduino.h&g…

Linux修改主机名称

hostnamectl set-hostname 主机名称 exit 退出登录重新进入即可

STM32 看门狗

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

一种简单有效的分析qnx+android智能座舱项目中的画面闪烁的方法(8155平台)

在智能座舱项目的开发过程中&#xff0c;画面闪烁问题是一个常见但棘手的挑战。由于这些闪烁现象往往转瞬即逝&#xff0c;传统的分析工具如截图、录屏或dump图层等方法难以捕捉和定位问题根源。针对这一难题&#xff0c;本文介绍了一种较为有效的分析方法&#xff0c;能够帮助…

ESP32 websocket-client

本文简介 ESP-IDF WebSocket-Client 实验平台 ①ESP-IDF 版本&#xff1a;release/v5.3.2 ③硬件平台&#xff1a;esp32-s3 版权声明 ①作者&#xff1a;coLin ②声明&#xff1a;问题总结&#xff0c;有误解&#xff0c;请联系纠正。 正文 1、基于 esp-idf 如何使用 …

MacOS下使用Ollama本地构建DeepSeek并使用本地Dify构建AI应用

目录 1 大白话说一下文章内容2 作者的电脑配置3 DeepSeek的本地部署3.1 Ollamal的下载和安装3.2 选择合适的deepseek模型3.3 安转deepseek 4 DifyDeepSeek构建Al应用4.1 Dify的安装4.1.1 前置条件4.1.2 拉取代码4.1.3 启动Dify 4.2 Dify控制页面4.3 使用Dify实现个“文章标题生…

DeepSeek写俄罗斯方块手机小游戏

DeepSeek写俄罗斯方块手机小游戏 提问 根据提的要求&#xff0c;让DeepSeek整理的需求&#xff0c;进行提问&#xff0c;内容如下&#xff1a; 请生成一个包含以下功能的可运行移动端俄罗斯方块H5文件&#xff1a; 核心功能要求 原生JavaScript实现&#xff0c;适配手机屏幕 …

DeepSeek 冲击(含本地化部署实践)

DeepSeek无疑是春节档最火爆的话题&#xff0c;上线不足一月&#xff0c;其全球累计下载量已达4000万&#xff0c;反超ChatGPT成为全球增长最快的AI应用&#xff0c;并且完全开源。那么究竟DeepSeek有什么魔力&#xff0c;能够让大家趋之若鹜&#xff0c;他又将怎样改变世界AI格…

2025 WE DAY品牌日| 天璇II WE X7 Pro充电桩震撼发布,能效电气开启充电革命

随着新能源产业的迅猛发展,充电桩作为电动汽车能量补给的重要基础设施,正在成为市场关注的焦点。能效电气作为充电桩领域的佼佼者,专注于研发高效、智能的充电解决方案,为电动汽车的普及与可持续发展铺设了坚实的基础。 2025年2月21日,能效电气在深圳盛大举办了以“以创新 引未…

Python(二十二)实现各大跨境船公司物流查询CMA船司物流查询

一、前言 本章主要实现 【之前CMA船司物流信息查询】的遗留问题 解决思路 由于CMA船司查询需要进行[机器人验证] 方法1&#xff1a;直接从前端跳过&#xff0c;用selenium实现前端自动化&#xff0c;查询物流信息 方法2&#xff1a;捕捉到接口search&#xff0c;但需要将返回…