C++ 线程 一些同步方式
- C++ 线程
- 一些同步方式
- 1.互斥锁(Mutex)
- 2. 读写锁(Reader-Writer Lock)
- 3. 信号量(Semaphore)
- 4. 原子操作(Atomic)
- 5. 屏障(Barrier)
- 6. 条件变量(Condition Variable)
一些同步方式
在多线程编程中,除了条件变量(condition variable)之外,还有其他几种常见的同步机制,每种机制都有其特定的使用场景和优势。以下是一些常见的同步方式:
1.互斥锁(Mutex)
互斥锁是最基本的同步机制,用于保护共享数据,防止多个线程同时访问导致数据竞争。
示例代码:
#include <iostream>
#include <thread>
#include <mutex>// 声明一个互斥锁对象
std::mutex mtx;// 声明一个共享数据变量,初始值为0
int shared_data = 0;// 线程函数:增加共享数据的值
void increment() {// 使用lock_guard锁定互斥锁,确保线程安全std::lock_guard<std::mutex> lock(mtx);// 增加共享数据的值shared_data++;
}int main() {// 创建两个线程,每个线程调用increment函数std::thread t1(increment);std::thread t2(increment);// 等待两个线程完成t1.join();t2.join();// 输出共享数据的最终值std::cout << "Shared data: " << shared_data << std::endl;// 返回0,表示程序正常结束return 0;
}
2. 读写锁(Reader-Writer Lock)
读写锁允许多个读线程同时访问共享数据,但写线程独占访问。适用于读多写少的场景。
示例代码:
#include <iostream>
#include <thread>
#include <shared_mutex>// 声明一个读写锁对象
std::shared_mutex rw_mtx;// 声明一个共享数据变量,初始值为0
int shared_data = 0;// 读线程函数:读取共享数据的值
void read() {// 使用shared_lock锁定读写锁,允许多个读线程同时访问std::shared_lock<std::shared_mutex> lock(rw_mtx);// 输出读取到的共享数据的值std::cout << "Read data: " << shared_data << std::endl;
}// 写线程函数:增加共享数据的值
void write() {// 使用unique_lock锁定读写锁,独占访问,阻止其他读写线程std::unique_lock<std::shared_mutex> lock(rw_mtx);// 增加共享数据的值shared_data++;// 输出写入后的共享数据的值std::cout << "Write data: " << shared_data << std::endl;
}int main() {// 创建一个读线程和一个写线程std::thread t1(read);std::thread t2(write);// 等待两个线程完成t1.join();t2.join();// 返回0,表示程序正常结束return 0;
}
3. 信号量(Semaphore)
信号量用于控制对共享资源的访问,可以用于线程间的同步和互斥。
示例代码:
#include <iostream>
#include <thread>
#include <semaphore>// 声明一个计数信号量对象,初始值为1
std::counting_semaphore<1> sem(1);// 声明一个共享数据变量,初始值为0
int shared_data = 0;// 线程函数:增加共享数据的值
void increment() {// 获取信号量,阻塞直到信号量可用sem.acquire();// 增加共享数据的值shared_data++;// 释放信号量,允许其他线程获取sem.release();
}int main() {// 创建两个线程,每个线程调用increment函数std::thread t1(increment);std::thread t2(increment);// 等待两个线程完成t1.join();t2.join();// 输出共享数据的最终值std::cout << "Shared data: " << shared_data << std::endl;// 返回0,表示程序正常结束return 0;
}
4. 原子操作(Atomic)
原子操作提供了一种无锁的同步机制,适用于对单个变量的简单操作。
示例代码:
#include <iostream>
#include <thread>
#include <atomic>// 声明一个原子整数变量,初始值为0
std::atomic<int> shared_data(0);// 线程函数:增加共享数据的值
void increment() {// 使用原子操作增加共享数据的值shared_data++;
}int main() {// 创建两个线程,每个线程调用increment函数std::thread t1(increment);std::thread t2(increment);// 等待两个线程完成t1.join();t2.join();// 输出共享数据的最终值std::cout << "Shared data: " << shared_data << std::endl;// 返回0,表示程序正常结束return 0;
}
5. 屏障(Barrier)
#include <iostream>
#include <thread>
#include <barrier>// 声明一个屏障对象,初始计数为3
std::barrier bar(3);// 工作线程函数:模拟工作并使用屏障进行同步
void worker() {// 输出工作线程开始的信息std::cout << "Worker started" << std::endl;// 到达屏障并等待,直到所有线程都到达屏障bar.arrive_and_wait();// 输出工作线程结束的信息std::cout << "Worker finished" << std::endl;
}int main() {// 创建三个线程,每个线程调用worker函数std::thread t1(worker);std::thread t2(worker);std::thread t3(worker);// 等待三个线程完成t1.join();t2.join();t3.join();// 返回0,表示程序正常结束return 0;
}
6. 条件变量(Condition Variable)
条件变量用于在一个线程等待某个条件成立时挂起该线程,并在条件成立时通知该线程继续执行。
示例代码:
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>// 声明一个互斥锁对象
std::mutex mtx;// 声明一个条件变量对象
std::condition_variable cv;// 声明一个布尔变量,用于表示条件是否成立
bool ready = false;// 工作线程函数:等待条件成立并开始工作
void worker() {// 使用unique_lock锁定互斥锁std::unique_lock<std::mutex> lock(mtx);// 等待条件变量,直到ready为truecv.wait(lock, []{ return ready; });// 输出工作线程开始的信息std::cout << "Worker started" << std::endl;
}// 触发线程函数:设置条件并通知等待的线程
void trigger() {// 使用lock_guard锁定互斥锁std::lock_guard<std::mutex> lock(mtx);// 设置ready为true,表示条件成立ready = true;// 通知一个等待的线程cv.notify_one();
}int main() {// 创建一个工作线程和一个触发线程std::thread t1(worker);std::thread t2(trigger);// 等待两个线程完成t1.join();t2.join();// 返回0,表示程序正常结束return 0;
}相关文章:
C++ 线程 一些同步方式
C 线程一些同步方式 1.互斥锁(Mutex)2. 读写锁(Reader-Writer Lock)3. 信号量(Semaphore)4. 原子操作(Atomic)5. 屏障(Barrier)6. 条件变量(Condi…...
【开发语言】编译型语言和解释性语言有啥区别?
作为一名从业多年的程序员,对于编译型语言和解释型语言之间的区别有着深入的理解。这两种类型的编程语言在将源代码转换成可执行代码的过程中采用了不同的机制,这导致了它们在执行效率、跨平台性、安全性以及开发效率等方面存在一些差异。 编译型语言(Compiled Languages)…...
将A服务器上指定文件夹中的文件,批量同步到B服务器上
需求:最近有一个需求,需要定期将A服务器上的PDF文件,同步到B服务器上,于是便写个脚本记录一下! 下面是使用Python3脚本实现的方法 import os import paramikodef copy_pdf_files(source_ip, source_user, source_pas…...
2024.8.17
130124202408171002 DATE #:20240817 ITEM #:DOC WEEK #:SATURDAY DAIL #:捌月拾肆 TAGS < BGM "快哉风 -- 黄金玉米王" > < theme oi-language > < theme oi-graph theory > < [空] > < [空] >取次花丛懒回顾,半缘修道…...
十分钟搭建一个RTMP服务器
使用SRS搭建RTMP服务器 如果您需要搭建一个RTMP服务器,您可以使用SRS(Simple-RTMP-Server)来完成此任务。SRS是一个开源的RTMP服务器下面是一个简单的步骤指南: 获取srs srs官⽹:https://github.com/ossrs/srs 码云…...
Spring Boot解决循环注入问题
Spring Boot解决循环依赖注入问题 代码问题回显启动错误日志解决方案:使用事件驱动或通过 ApplicationContext 手动获取 Bean1. 事件驱动设计2. 使用 ApplicationContext 手动获取 Bean3. 拆分逻辑 总结 代码问题回显 现有代码1 在InterestService中依赖MemberInte…...
《数据挖掘》期末考核重点
1.数据预处理的目的与形式 数据预处理的目的是提供干净,简洁,准确的数据,以达到简化模型和提高算法泛化能力的目的,使挖掘过程更有效,更容易,提高挖掘效率和准确性。 2.数据预处理的形式 数据清理&#…...
Golang | Leetcode Golang题解之第334题递增的三元子序列
题目: 题解: func increasingTriplet(nums []int) bool {n : len(nums)if n < 3 {return false}first, second : nums[0], math.MaxInt32for i : 1; i < n; i {num : nums[i]if num > second {return true} else if num > first {second n…...
HarmonyOs编写一个案例实现一个照片选择(阶段进阶 四种需求 逐一完善)
需求1. .实现照片选择 并将选择好的照片展示出来 import { GoodItem } from ../06/modules;Entry Component struct PhotoPage {State message: string 实现一个相册;State List: GoodItem[] [{goods_name: dsfjlsjkfsf,goods_price: 100,goods_img: https://img1.baidu.com…...
洗衣机洗衣服一些知识
01智能:按衣物多少自动调节合适水位的标准洗涤程序 (需要30分钟时间) 02:大物:较大,较厚的衣服洗涤 03:轻柔:毛织品或内衣洗涤 04:快速:少量清污衣服洗涤 (13分钟) 05:浸泡:先浸泡一段时间再洗涤 06:单洗:只洗衣不脱水 07:单脱:只脱水不洗衣 08:洁桶:清洁洗衣桶 准备工作: (1)…...
探索文件系统:高效、可靠的文件管理与访问机制
文件系统的功能规划 内存就像是一个书包,容量有限,只能带着一部分东西。而图书馆则是一个专门存储和管理文件的地方,拥有更大的容量,并且可以永久保存文件。为了能够快速找到需要的文件,我们需要有一个书单来记录每本…...
启程与远征Ⅸ--优化生成式人工智能以满足业务需求的框架
生成类似人类的文本和语音曾经只存在于科幻小说中。但 GPT-3 和 PaLM 等大型语言模型 (LLM) 的快速发展让这一愿景更接近现实,解锁了从聊天机器人到内容创作等一系列有前景的商业应用。 然而,通用基础模型往往无法满足行业用例的需求。企业对其生成式 A…...
canal数据同步工具介绍与应用
canal服务 canal介绍canal版本与环境canal 服务集canal应用场景: canal常见问题xml配置问题连接认证问题jar版本问题连接问题 canal介绍 1、Canal是阿里巴巴开源的MySQL增量数据订阅和消费工具,通过模拟MySQL的slave与master交互,捕…...
ubuntu18.04 设置静态地址
修改配置文件 sudo vim /etc/netplan/01-network-manager-all.yaml 代码如下: network: version: 2 renderer: NetworkManager ethernets: ens33: # 配置的网卡名称,可以使用ifconfig -a查看本机的网卡 dhcp4: no # 关闭动态IP设置 …...
jira敏捷开发管理工具视频教程Confluence工作流协同开发(2024)
正文: 随着Jira敏捷开发方法论的普及,Jira已经成为全球软件开发团队管理项目、任务和问题的首选工具。为了帮助团队更好地掌握Jira的核心功能,精心准备了一套全面开发技术及案例视频教程——《Jira敏捷开发管理工具视频教程Confluenc…...
【网络】TCP回显服务器和客户端的构造,以及相关bug解决方法
文章目录 ServerSocket构造方法方法 Socket构造方法方法 回显服务器(Echo Server)1. 构造方法2. 建立连接processConnection 方法的创建1. 读取请求并解析2. 根据请求计算响应3. 把响应写回给客户端 3. 完整代码 客户端(Echo Clientÿ…...
Python知识点:如何使用Boto3进行AWS服务管理
使用 boto3 来管理 AWS 服务是一个非常强大的方式,因为 boto3 是 AWS 提供的官方 Python SDK。下面是使用 boto3 管理 AWS 服务的基本步骤,包括设置、操作和常见的 AWS 服务示例。 1. 安装 boto3 首先,确保你已经安装了 boto3。可以使用 pi…...
Java - 正则表达式
Java 提供了 java.util.regex 包,它包含了 Pattern 和 Matcher 类,用于处理正则表达式的匹配操作。 正则表达式的模式 正则表达式的模式可以包括以下内容: 字面值字符:例如字母、数字、空格等,可以直接匹配它们自身。…...
Vue一款流行的JavaScript前端框架
1.Vue简介 Vue是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。无论是简单还是复杂的界面,Vue 都可以胜任。 Vue所关注的核心是MVC…...
GPT-SoVITS
文章目录 model archS1 ModelS2 model model arch S1 model: AR model–ssl tokensS2 model: VITS,ssl 已经是mel 长度线性相关,MRTE(ssl_codes_embs, text, global_mel_emb)模块,将文本加强相关,学到一个参考结果 S1 Model cla…...
VisDrone2019数据集转换COCO格式实战:手把手教你用Python脚本搞定YOLOX训练数据准备
VisDrone2019数据集转换COCO格式全流程解析:从数据清洗到YOLOX适配 无人机视角下的目标检测一直是计算机视觉领域的特殊挑战。VisDrone2019作为该领域最具代表性的开源数据集,包含了10个类别、超过26万张标注图像,但原始数据格式与主流框架的…...
手把手教你用UE5 C++为角色添加动态攀爬:支持移动平台与高度自适应
手把手实现UE5动态攀爬系统:移动平台与高度自适应全解析 在当代3A级动作游戏中,角色与环境的动态交互已成为沉浸感的核心要素。想象一个场景:玩家在摇晃的空中浮岛上追逐目标,需要连续攀爬移动中的平台;或是潜入敌方基…...
极域电子教室破解指南:3分钟重获电脑自主权,学习效率翻倍
极域电子教室破解指南:3分钟重获电脑自主权,学习效率翻倍 【免费下载链接】JiYuTrainer 极域电子教室防控制软件, StudenMain.exe 破解 项目地址: https://gitcode.com/gh_mirrors/ji/JiYuTrainer 你是否曾在机房上课时,面对老师全屏广…...
手把手教你用Wireshark(或类似工具)理解AMBA AXI总线上的数据流(以Cortex-A53为例)
实战解析:用Wireshark透视Cortex-A53的AXI总线数据流 在嵌入式系统开发中,AXI总线如同SoC的神经系统,承载着处理器核心与各功能模块间的关键通信。对于底层驱动工程师和FPGA开发者而言,能够直观观察总线上的数据流动,就…...
Codex+Coze自动化工作流实战
Codex(特指OpenAI的编程特化AI Agent)与Coze(扣子)平台的结合,能够实现从自然语言描述到可运行自动化流程的端到端生成。其核心在于利用Codex强大的代码理解和生成能力,来编写、调试并封装符合Coze平台规范…...
保姆级教程:在小米/华为手机上从零安装AidLux,并解决首次启动卡顿问题
保姆级教程:在小米/华为手机上从零安装AidLux,并解决首次启动卡顿问题 对于移动端开发者和AI爱好者来说,在安卓手机上运行Linux环境一直是个痛点。AidLux作为一款创新的跨生态AI应用开发平台,完美解决了这一需求。本文将针对小米和…...
2026年AI搜索优化服务商TOP10榜单发布:技术原生派领跑,垂直专精派各显神通
随着生成式AI全面重构用户信息获取与消费决策路径,AI搜索优化(GEO)已从概念验证迈入规模化落地阶段。企业面临的痛点高度集中:技术门槛高、效果难量化、服务商良莠不齐。为帮助企业精准选型,我们基于技术自研能力、实战…...
Spike Prime避坑指南:Python控制电机和传感器时,新手最常遇到的5个错误及解决方法
Spike Prime避坑指南:Python控制电机和传感器时新手最常遇到的5个错误 第一次用Python控制Spike Prime的电机和传感器时,那种期待和兴奋很快就会被各种报错消磨殆尽。明明照着官方文档写的代码,电机就是不转;传感器读数永远为零&a…...
从光猫到路由器:DHCP、PPPoE、静态IP三种连接方式的底层原理与实战抓包分析
从光猫到路由器:DHCP、PPPoE、静态IP三种连接方式的底层原理与实战抓包分析 当你面对家庭或企业网络配置时,是否曾疑惑过为什么不同的网络环境会采用截然不同的连接方式?本文将带你深入三种主流上网方式的技术本质,通过Wireshark抓…...
ArduPilot硬件抽象层(HAL)深度解析:如何让你的飞控代码轻松跑在不同芯片上?
ArduPilot硬件抽象层(HAL)深度解析:跨平台飞控开发实战指南 当开发者尝试将ArduPilot移植到一块全新的飞控板时,最常遇到的挑战莫过于如何让同一套控制算法在不同硬件架构上无缝运行。这正是硬件抽象层(HAL)设计的精妙之处——它如同一位技艺高超的翻译官…...
