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…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...

ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...
Git常用命令完全指南:从入门到精通
Git常用命令完全指南:从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...
人工智能 - 在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型
在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型。这些平台各有侧重,适用场景差异显著。下面我将从核心功能定位、典型应用场景、真实体验痛点、选型决策关键点进行拆解,并提供具体场景下的推荐方案。 一、核心功能定位速览 平台核心定位技术栈亮…...