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…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...

STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
作为测试我们应该关注redis哪些方面
1、功能测试 数据结构操作:验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化:测试aof和aof持久化机制,确保数据在开启后正确恢复。 事务:检查事务的原子性和回滚机制。 发布订阅:确保消息正确传递。 2、性…...