C++11 之 【线程库】(condition_variable、atomic、线程交替打印奇偶数、谓词、线程总结)
目录1.condition_variablewait()无谓词版本wait()带谓词版本wait_for()无谓词版本wait_for()带谓词版本wait_until()无谓词版本wait_until()带谓词版本notify_one()notify_all()注意事项2.两个线程交替打印奇偶数3.atomic默认构造函数初始化构造函数拷贝构造函数删除拷贝赋值操作符删除store()load()exchange()compare_exchange_weak()compare_exchange_strong()atomic 常用接口简介4.总结一、线程基础概念5问二、线程生命周期3问三、线程安全问题核心难点四、生产者消费者模型经典同步案例五、设计模式六、进阶同步机制1.condition_variablestd::condition_variable是 C11 提供的条件变量用于线程间的同步通信允许一个线程等待某个条件成立另一个线程通知等待线程条件已满足。需要与互斥锁通常为std::unique_lockstd::mutex配合使用术语说明谓词返回布尔值true/false的可调用对象用于判断某个条件是否满足谓词版本函数包含谓词参数的版本内部自动循环检查条件避免虚假唤醒对比维度无谓词版本谓词版本接口cv.wait(lock)cv.wait(lock, pred)返回值voidvoid或超时版本返回bool虚假唤醒可能发生返回后条件不一定成立自动处理只有谓词为true才返回使用方式需要手动循环检查条件内部自动循环检查wait()无谓词版本项目说明接口名称void wait(std::unique_lockstd::mutex lock);功能描述阻塞当前线程直到被通知或虚假唤醒。调用时会原子性地释放锁并阻塞线程被唤醒后重新获取锁参数lock已经持有的unique_lock对象必须已锁定返回值无使用示例std::unique_lockstd::mutex lock(mtx);cv.wait(lock);注意事项调用前必须已持有锁可能虚假唤醒返回后条件不一定成立被唤醒后需重新检查条件wait()带谓词版本项目说明接口名称templateclass Predicate void wait(std::unique_lockstd::mutex lock, Predicate pred);功能描述带谓词的等待只有当谓词返回 false 时才阻塞。等价于while (!pred()) wait(lock);参数lock已经持有的unique_lock对象pred可调用对象返回 bool 值返回值无使用示例cv.wait(lock, []{ return data_ready; });注意事项推荐使用自动处理虚假唤醒内部自动循环检查谓词被唤醒时谓词为 true 才返回wait_for()无谓词版本项目说明接口名称templateclass Rep, class Period cv_status wait_for(std::unique_lockstd::mutex lock, const std::chrono::durationRep, Period rel_time);功能描述等待指定时长超时或被通知后返回。期间会释放锁并阻塞参数lock已经持有的unique_lock对象rel_time要等待的相对时间长度返回值cv_status::timeout超时返回cv_status::no_timeout被通知唤醒使用示例cv.wait_for(lock, std::chrono::seconds(1));注意事项也可能发生虚假唤醒建议与谓词结合使用实际等待时间可能略长于指定时间wait_for()带谓词版本项目说明接口名称templateclass Rep, class Period, class Predicate bool wait_for(std::unique_lockstd::mutex lock, const std::chrono::durationRep, Period rel_time, Predicate pred);功能描述带谓词的超时等待在超时前如果谓词变为 true 则返回 true超时返回 false参数lock已经持有的unique_lock对象rel_time相对时间长度pred条件谓词返回值true谓词变为 truefalse超时且谓词仍为 false使用示例cv.wait_for(lock, 1s, []{ return flag; });注意事项推荐使用的超时等待方式自动处理虚假唤醒等价于循环检查谓词和超时wait_until()无谓词版本项目说明接口名称templateclass Clock, class Duration cv_status wait_until(std::unique_lockstd::mutex lock, const std::chrono::time_pointClock, Duration abs_time);功能描述等待到指定时间点超时或被通知后返回。期间会释放锁并阻塞参数lock已经持有的unique_lock对象abs_time绝对时间点返回值cv_status::timeout超时返回cv_status::no_timeout被通知唤醒使用示例cv.wait_until(lock, steady_clock::now() 5s);注意事项受系统时钟调整影响可能虚假唤醒建议与谓词结合使用wait_until()带谓词版本项目说明接口名称templateclass Clock, class Duration, class Predicate bool wait_until(std::unique_lockstd::mutex lock, const std::chrono::time_pointClock, Duration abs_time, Predicate pred);功能描述带谓词的绝对时间等待在超时前如果谓词变为 true 则返回 true超时返回 false参数lock已经持有的unique_lock对象abs_time绝对时间点pred条件谓词返回值true谓词变为 truefalse超时且谓词仍为 false使用示例cv.wait_until(lock, deadline, []{ return flag; });注意事项推荐使用的绝对时间等待方式自动处理虚假唤醒使用 steady_clock 避免时钟调整影响notify_one()项目说明接口名称void notify_one() noexcept;功能描述唤醒一个正在等待该条件变量的线程。如果有多个线程等待选择其中一个唤醒参数无返回值无使用示例cv.notify_one();注意事项不需要持有锁即可调用被唤醒的线程需要重新获取锁适用于生产者-消费者模型中的单个通知notify_all()项目说明接口名称void notify_all() noexcept;功能描述唤醒所有正在等待该条件变量的线程参数无返回值无使用示例cv.notify_all();注意事项不需要持有锁即可调用可能引起“惊群效应”适合广播场景如程序退出、批量任务注意事项注意事项说明必须与互斥锁配合不能单独使用必须配合std::unique_lockstd::mutex虚假唤醒wait 可能在没有被通知的情况下返回必须用循环或谓词检查条件持有锁才能调用wait 系列函数调用前必须已持有锁notify 不需要持有锁通知时可以在锁外调用提高并发性能谓词版本优先总是优先使用带谓词的 wait避免虚假唤醒问题wait_for/wait_until超时等待可能因调度延迟而超时需检查返回值性能考虑频繁 notify_all 可能引起惊群效应2.两个线程交替打印奇偶数#include iostream #include vector #include thread #include mutex using namespace std; //两个线程交替打印奇偶数 int main() { int x 1;//递增变量 mutex lock;//互斥锁 condition_variable cv;//条件变量用户等待 bool flag false;//标志位控制交替 //t1打印奇数 thread t1([]() { for (int i 0; i 50; i) { //互斥锁保证原子性 unique_lockmutex guard(lock); //flag为真就去条件队列等待 while(flag) cv.wait(guard); cout t1_id- this_thread::get_id() cout: x endl; x; flag true; //奇数打印完毕唤醒t2线程 cv.notify_one(); } }); //t2打印偶数 thread t2([]() { for (int i 0; i 50; i) { //互斥锁保证原子性 unique_lockmutex guard(lock); //flag为假就去条件队列等待 while(!flag) cv.wait(guard); cout t2_id- this_thread::get_id() cout: x endl; x; flag false; //偶数打印完毕唤醒t1线程 cv.notify_one(); } }); t1.join(); t2.join(); return 0; }知识点说明互斥锁保护共享资源x和flag防止数据竞争条件变量实现线程间等待与唤醒控制执行顺序unique_lockRAII风格的锁管理配合条件变量使用必须用unique_lock不能是lock_guard标志位flag控制交替逻辑false→t1打印奇数true→t2打印偶数互斥锁保证共享数据安全条件变量配合标志位实现线程交替执行while循环处理虚假唤醒RAII管理锁资源3.atomicstd::atomic是 C11 提供的原子操作模板类用于实现无锁编程保证对共享变量的操作是原子性的避免数据竞争默认构造函数项目说明接口名称atomic() noexcept;功能描述创建未初始化的原子对象参数无使用示例std::atomicint a;注意事项后续需要显式初始化未初始化的对象值未定义初始化构造函数项目说明接口名称atomic(T desired) noexcept;功能描述使用初始值构造原子对象参数desired初始值使用示例std::atomicint a(10);注意事项构造操作是原子的拷贝构造函数删除项目说明接口名称atomic(const atomic) delete;功能描述拷贝构造函数被显式删除注意事项原子对象不可复制拷贝赋值操作符删除项目说明接口名称operator(const atomic) delete;功能描述拷贝赋值操作符被显式删除注意事项原子对象不可复制赋值原子对象不可复制和赋值的原因是为了保证原子操作的唯一性和硬件级别的原子性保障每个原子对象直接映射到硬件支持的原子内存位置原子指令如CAS必须直接作用于该内存地址。如果允许复制或赋值会创建出多个对象试图控制同一内存区域导致操作混乱、原子性失效。因此C强制开发者明确每个原子变量的唯一身份禁止拷贝语义确保所有操作都直接作用于原始内存位置避免数据竞争和未定义行为从而维持无锁编程的正确性和性能优势store()项目说明接口名称void store(T desired, memory_order order memory_order_seq_cst) noexcept;功能描述将值存储到原子变量中参数desired要存储的值order内存序返回值无使用示例a.store(10);注意事项默认顺序一致性可指定宽松内存序常见默认了解load()项目说明接口名称T load(memory_order order memory_order_seq_cst) const noexcept;功能描述加载原子变量的当前值参数order内存序返回值原子变量的当前值使用示例int x a.load();注意事项读取操作是原子的exchange()项目说明接口名称T exchange(T desired, memory_order order memory_order_seq_cst) noexcept;功能描述将值替换为新值并返回旧值原子读-改-写操作参数desired新值order内存序返回值交换前的旧值使用示例int old a.exchange(20);注意事项原子地完成读和写操作compare_exchange_weak()项目说明接口名称bool compare_exchange_weak(T expected, T desired, memory_order success, memory_order failure) noexcept;功能描述弱版本CAS操作如果当前值等于expected则更新为desired并返回true否则将expected更新为当前值并返回false参数expected期望值引用desired新值success/failure成功/失败内存序返回值true交换成功false交换失败使用示例int expected 10;bool success a.compare_exchange_weak(expected, 20);注意事项可能虚假失败需循环重试性能优于强版本compare_exchange_strong()项目说明接口名称bool compare_exchange_strong(T expected, T desired, memory_order success, memory_order failure) noexcept;功能描述强版本CAS操作如果当前值等于expected则更新为desired并返回true否则将expected更新为当前值并返回false参数expected期望值引用desired新值success/failure成功/失败内存序返回值true交换成功false交换失败使用示例int expected 10;bool success a.compare_exchange_strong(expected, 20);注意事项不会虚假失败但可能性能略低于弱版本atomic 常用接口简介接口分类接口名称功能简述存储加载store()原子存储值load()原子加载值operator T()隐式转换为 Toperator赋值操作读写修改exchange()交换并返回旧值compare_exchange_weak()弱 CAS可能虚假失败compare_exchange_strong()强 CAS无虚假失败算术运算fetch_add()、fetch_sub()原子加减返回旧值operator、operator--前置/后置自增自减operator、operator-算术赋值位运算fetch_and()、fetch_or()、fetch_xor()原子位运算返回旧值operator、operator|、operator^位运算赋值4.总结一、线程基础概念5问问题核心内容什么是线程CPU调度的最小单位进程内的执行流如何理解线程轻量级进程共享进程资源独立栈和寄存器进程 vs 线程资源分配单位 vs 调度单位隔离性 vs 共享性系统层面重构从进程模型到线程模型的演进用户级 vs 内核级线程可重入 vs 线程安全可重入函数被中断重入线程安全多线程并发安全二、线程生命周期3问问题核心内容线程控制创建、终止、等待、分离创建与终止pthread_create、exit、return线程等待pthread_join、分离线程detach三、线程安全问题核心难点问题分类具体问题解决方案互斥问题数据竞争、临界区互斥锁mutex同步问题执行顺序控制条件变量、信号量死锁问题互相等待锁顺序、trylock、RAII四、生产者消费者模型经典同步案例模型数据结构特点阻塞队列模型队列空间无限逻辑上操作简单环形队列模型数组头尾指针空间有限高效复用线程池任务队列工作线程避免频繁创建销毁线程五、设计模式模式应用场景线程安全实现单例模式全局唯一实例饿汉、懒汉双重判空、局部静态六、进阶同步机制机制特点适用场景自旋锁忙等待不阻塞临界区极短读写锁读共享、写独占读多写少信号量计数同步资源计数屏障多线程汇合分治算法

相关新闻

照着用就行:专科生专属降AI工具 —— 千笔·降AI率助手

照着用就行:专科生专属降AI工具 —— 千笔·降AI率助手

在AI技术席卷学术写作的今天,越来越多的学生、研究人员和职场人士选择借助AI辅助完成论文、报告和学术材料。然而,随之而来的“AI率超标”问题却成为横亘在学术道路上的隐形障碍——知网、维普、万方等主流查重系统纷纷升级算法,严打AI生成内…

2026/7/5 18:05:03 阅读更多 →
Linux 之 【多线程】(STL、智能指针与线程安全、读者写者问题)

Linux 之 【多线程】(STL、智能指针与线程安全、读者写者问题)

目录 1.STL、智能指针与线程安全 STL容器默认不是线程安全的 智能指针线程安全 2.读者写者问题 背景 读写锁核心特性 321原则 优先级策略 POSIX读写锁接口 读写锁示例 设置写者优先示例 1.STL、智能指针与线程安全 STL容器默认不是线程安全的 多线程环境下需要调用…

2026/7/6 12:53:56 阅读更多 →
FastDDS是什么?如何进行源码编译?

FastDDS是什么?如何进行源码编译?

目录一、Ubuntu系统介绍二、FastDDS是什么三、FastDDS的源码编译四、FastDDS的简单测试一、Ubuntu系统介绍 Ubuntu是一个基于Linux的开源操作系统,由Canonical公司开发和维护。它以其易用性、稳定性和安全性而受到广泛赞誉。Ubuntu系统提供了一个图形化的桌面环境&…

2026/7/4 10:03:52 阅读更多 →

最新新闻

SeetaFace6实战:从零构建C# WinForm人脸多属性检测系统

SeetaFace6实战:从零构建C# WinForm人脸多属性检测系统

1. 环境准备与SDK集成在开始构建人脸多属性检测系统之前,我们需要准备好开发环境。首先确保你的Windows系统是64位版本(Win7及以上),并安装Visual Studio 2019或更高版本。我推荐使用.NET Framework 4.7.2以上版本,这是…

2026/7/6 12:53:38 阅读更多 →
免费文档下载神器:一键获取百度文库、道客巴巴等30+平台学习资料

免费文档下载神器:一键获取百度文库、道客巴巴等30+平台学习资料

免费文档下载神器:一键获取百度文库、道客巴巴等30平台学习资料 【免费下载链接】kill-doc 看到经常有小伙伴们需要下载一些免费文档,但是相关网站浏览体验不好各种广告,各种登录验证,需要很多步骤才能下载文档,该脚本…

2026/7/6 12:53:38 阅读更多 →
OpenCV 4.8 频域滤波实战:3步消除图像边缘效应与指纹环带分析

OpenCV 4.8 频域滤波实战:3步消除图像边缘效应与指纹环带分析

OpenCV频域滤波实战:消除边缘效应与指纹环带分析的三步法则频域滤波的核心挑战与解决方案当我们把图像从空间域转换到频域进行分析时,总会遇到两个典型问题:图像边缘突变导致的频谱干扰和特定纹理(如指纹)的环状频域特…

2026/7/6 12:51:36 阅读更多 →
OpenCV 4.8 图像频域分析实战:5种经典纹理频谱特征提取与可视化

OpenCV 4.8 图像频域分析实战:5种经典纹理频谱特征提取与可视化

OpenCV 4.8 图像频域分析实战:5种经典纹理频谱特征提取与可视化在数字图像处理领域,频域分析为我们打开了观察图像的全新视角。通过傅里叶变换,我们能够将图像从空间域转换到频率域,揭示隐藏在像素背后的周期性结构和纹理特征。本…

2026/7/6 12:51:36 阅读更多 →
DBNet 文本检测实战:基于PaddleOCR 2.7 从训练到部署的5个关键步骤

DBNet 文本检测实战:基于PaddleOCR 2.7 从训练到部署的5个关键步骤

DBNet文本检测实战:基于PaddleOCR 2.7的工业级落地指南当OCR技术遇上复杂多变的现实场景,传统文本检测方法往往在弯曲文本、密集排列或低对比度环境下表现乏力。DBNet(Differentiable Binarization)通过将二值化过程融入神经网络架…

2026/7/6 12:51:36 阅读更多 →
KMS_VL_ALL_AIO:3分钟搞定Windows和Office激活的智能工具箱

KMS_VL_ALL_AIO:3分钟搞定Windows和Office激活的智能工具箱

KMS_VL_ALL_AIO:3分钟搞定Windows和Office激活的智能工具箱 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO 还在为Windows和Office激活烦恼吗?面对复杂的命令行工具不知所…

2026/7/6 12:51:36 阅读更多 →

日新闻

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2与MySQL单元测试兼容性:5个关键SQL语句差异与规避方案1. 单元测试中的数据库兼容性挑战在Java开发领域,单元测试是保证代码质量的重要环节。当应用涉及数据库操作时,测试环境的搭建往往成为开发者的痛点。H2数据库因其轻量级、内存模式和快…

2026/7/6 0:01:17 阅读更多 →
Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘 【免费下载链接】rbtray A fork of RBTray from http://sourceforge.net/p/rbtray/code/. 项目地址: https://gitcode.com/gh_mirrors/rb/rbtray 你是否厌倦了Windows任务栏上密密麻麻的图标&…

2026/7/6 0:01:17 阅读更多 →
Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C 运行时库一键安装终极指南:告别DLL缺失烦恼 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾经遇到过这样的情况:下载了…

2026/7/6 0:05:19 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/6 8:11:50 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/6 8:11:52 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/6 6:52:56 阅读更多 →

月新闻