从零理解 C++ 中的原子布尔变量:`std::atomic<bool>` 入门指南
文章目录
- 引言:为什么需要原子变量?
- 一、什么是 `std::atomic<bool>`?
- 二、为什么不用普通 `bool`?一个反面例子
- 三、`std::atomic<bool>` 的用法
- 四、`std::atomic<bool>` 的优势
- 五、完整示例:多线程文件传输
- 六、注意事项
- 七、总结
引言:为什么需要原子变量?
想象这样一个场景:你正在写一个多线程程序,其中一个线程负责传输文件,另一个线程需要实时检查传输是否完成。如果用一个普通的 bool
变量(例如 bool transFileRet = false;
)来标记传输结果,可能会遇到意想不到的问题——程序偶尔会“抽风”,明明传输完成了,另一个线程却看不到结果,甚至直接崩溃!
问题的根源在于:普通的变量在多线程环境中不是“线程安全”的。为了解决这个问题,C++11 引入了 std::atomic
模板,而 std::atomic<bool>
正是用于布尔类型的高效线程安全工具。本文将带你一步步理解它的用法和原理。
一、什么是 std::atomic<bool>
?
🚩1. 原子操作:不可分割的“最小单位”
原子操作指的是在多线程环境中,某个操作一旦开始,就会一次性完整执行,不会被其他线程打断。例如:
transFileRet = true; // 如果是原子操作,其他线程只会看到赋值前或赋值后的状态
🚩2. std::atomic<bool>
的定义
#include <atomic> // 必须包含头文件std::atomic<bool> transFileRet{false}; // 初始化一个原子布尔变量,初始值为 false
• transFileRet
是一个布尔变量,但所有对它的操作(读、写、修改)都是原子的。
• 它属于 C++ 标准库,需包含 <atomic>
头文件。
二、为什么不用普通 bool
?一个反面例子
🚩错误代码示例
bool transFileRet = false; // 普通布尔变量// 线程1:传输完成后设置结果
void worker_thread() {// ... 传输文件的逻辑 ...transFileRet = true; // 非原子操作!
}// 线程2:循环检查结果
void main_thread() {while (!transFileRet) { // 非原子读取!// 等待传输完成...}// 处理传输完成后的逻辑
}
🚩可能的问题
-
数据竞争(Data Race)
如果两个线程同时读写transFileRet
,可能导致未定义行为(程序崩溃、结果错误等)。 -
可见性问题
线程1修改了transFileRet
,但线程2可能因为CPU缓存或编译器优化,永远看不到最新的值。 -
指令重排
编译器或CPU可能优化代码顺序,导致逻辑错误。
三、std::atomic<bool>
的用法
🚩1. 基本操作
std::atomic<bool> flag{false};// 写入值(原子操作)
flag.store(true); // 设置为 true
flag.store(false); // 设置为 false// 读取值(原子操作)
bool value = flag.load(); // 获取当前值// 原子地交换值
bool old_value = flag.exchange(true); // 返回旧值,设置新值为 true
🚩2. 等待与通知(C++20 起支持)
C++20 新增了针对原子变量的等待/通知接口,可以更高效地实现线程同步:
// 线程1:设置标记并通知
flag.store(true);
flag.notify_all(); // 唤醒所有等待的线程// 线程2:等待标记变为 true
flag.wait(false); // 当前值为 false 时等待,否则继续执行
四、std::atomic<bool>
的优势
🚩1. 无锁线程安全
• 传统方式需要用 std::mutex
保护布尔变量:
std::mutex mtx;
bool transFileRet = false;// 写操作
{std::lock_guard<std::mutex> lock(mtx);transFileRet = true;
}// 读操作
{std::lock_guard<std::mutex> lock(mtx);if (transFileRet) { ... }
}
• std::atomic<bool>
无需加锁,通过底层硬件指令(如 CAS
)实现原子性,性能更高。
🚩2. 内存顺序可控
• 可以通过参数指定内存顺序,平衡性能与一致性(默认是强顺序一致性 memory_order_seq_cst
):
flag.store(true, std::memory_order_release); // 写入时使用 release 语义
bool val = flag.load(std::memory_order_acquire); // 读取时使用 acquire 语义
🚩3. 避免编译器/CPU 优化
• 确保修改对其他线程立即可见。
• 禁止编译器或CPU对指令进行不安全的重新排序。
五、完整示例:多线程文件传输
#include <iostream>
#include <atomic>
#include <thread>
#include <chrono>std::atomic<bool> transFileRet{false}; // 原子布尔变量// 模拟文件传输线程
void transmit_file() {std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟传输耗时transFileRet.store(true); // 原子写入:传输完成std::cout << "传输完成!" << std::endl;
}// 模拟主线程等待结果
void check_status() {while (!transFileRet.load()) { // 原子读取std::cout << "等待中..." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(500));}std::cout << "检测到传输完成!" << std::endl;
}int main() {std::thread worker(transmit_file);std::thread checker(check_status);worker.join();checker.join();return 0;
}
输出示例:
等待中...
等待中...
等待中...
等待中...
传输完成!
检测到传输完成!
六、注意事项
🚩1. 适用场景
std::atomic<bool>
适合简单的状态标记(如完成标志、开关标志)。若需要保护多个变量的复合操作,仍需使用互斥锁。
🚩2. 性能开销
虽然原子操作比锁更高效,但频繁的原子操作(如循环检查)仍可能影响性能。考虑结合条件变量(std::condition_variable
)使用。
🚩3. 内存顺序
大多数情况下使用默认的 memory_order_seq_cst
即可。若对性能有极致要求,可学习更弱的内存顺序(如 relaxed
)。
七、总结
• 用 std::atomic<bool>
替代普通 bool
当需要在多线程中共享布尔变量时,原子类型是安全且高效的选择。
• 核心优势
无锁、线程安全、高性能、避免优化问题。
• 进一步学习
• 了解其他原子类型(如 std::atomic<int>
)。
• 学习内存顺序(C++ Memory Model)。
• 探索 C++20 的原子等待/通知接口。
动手尝试:
将你之前写的某个多线程程序中的普通 bool
变量改为 std::atomic<bool>
,观察是否解决了偶发的线程同步问题!
相关文章:

从零理解 C++ 中的原子布尔变量:`std::atomic<bool>` 入门指南
文章目录 引言:为什么需要原子变量?一、什么是 std::atomic<bool>?二、为什么不用普通 bool?一个反面例子三、std::atomic<bool> 的用法四、std::atomic<bool> 的优势五、完整示例:多线程文件传输六…...
软件领域第三方检测机构:如何保障软件品质与安全?
在软件领域,第三方检测机构扮演着极其重要的角色,它们与软件开发者和使用者保持独立,对软件的品质和安全性进行公正而专业的评估。凭借严格的技术方法和丰富的实践经历,这些机构能够揭示软件中潜藏的问题,进而确保软件…...
单例模式的两种设计
单例模式确保一个类只有一个实例,并提供一个全局访问点。 1. 饿汉模式 (Eager Initialization) 饿汉模式在程序启动时就创建实例,线程安全。 cpp class EagerSingleton { public:// 删除拷贝构造函数和赋值运算符EagerSingleton(const EagerSingleton…...
MySQL 5.7 之后的特性解析:从 8.0 到 8.4 的技术进化
MySQL 是全球最流行的开源关系型数据库之一,广泛应用于 Web 应用、数据分析和企业级系统。自 MySQL 5.7(2015 年发布)以来,MySQL 8.0(2018 年)、8.1(2023 年)、8.4(2024 …...
PHP框架在分布式系统中的应用!
随着互联网业务的快速发展,分布式系统因其高可用性、可扩展性和容错性成为现代应用架构的主流选择。而PHP作为一门成熟的Web开发语言,凭借其简洁的语法、丰富的框架生态和持续的性能优化,逐渐在分布式系统中崭露头角。本文将深入探讨PHP框架在…...
[学习]RTKLib详解:ionex.c、options.c与preceph.c
RTKLib详解:ionex.c、options.c与preceph.c 本文是 RTKLlib详解 系列文章的一篇,目前该系列文章还在持续总结写作中,以发表的如下,有兴趣的可以翻阅。 [学习] RTKlib详解:功能、工具与源码结构解析 [学习]RTKLib详解&…...

六个仓库合并为一个仓库,保留master和develop分支的bat脚本
利用git subtree可以实现多个仓库合并为一个仓库,手动操作起来太麻烦了,今天花了点时间写了一个可执行的脚本,现在操作起来就方便多了。 1、本地新建setup.bat文件 2、用编辑器打开(我用的是Notepad) 3、把下面代码…...

养生:通往健康生活的桥梁
在生活节奏日益加快的今天,养生已成为维持身心健康的必要手段。从日常饮食到运动锻炼,从睡眠质量到心态调节,每一个环节都对我们的生活品质有着重要影响。以下是一些实用的养生建议,帮助你打造健康生活。 饮食养生:均…...

【前端基础】9、CSS的动态伪类(hover、visited、hover、active、focus)【注:本文只有几个粗略说明】
一、什么是伪类 选择器的一种,用于选择处于特定状态的元素。 最常见的现象:鼠标放在某些文字上面,文字就会加上颜色。 鼠标没放上去之前: 鼠标放上去之后: 二、动态伪类 图片来源(链接文章也有其他伪…...

Simufact Welding重塑新能源汽车电池盒焊接工艺
引言 近年来,新能源汽车行业呈爆发式增长,已然成为全球能源转型与汽车产业升级的核心方向。在新能源汽车中,电池系统占据核心地位,作为电池系统重要组成部分的电池盒,也发挥着不可或缺的作用 。目前,电池盒…...

WordPress 网站上的 jpg、png 和 WebP 图片插件
核心功能 1. 转换 AVIF 并压缩 AVIF 将您 WordPress 网站上的 jpg、png 和 WebP 图片转换为 AVIF 格式,并根据您设置的压缩级别压缩 AVIF 图片。如果原始图片已经是 WordPress 6.5 以上支持的 AVIF 格式,则原始 AVIF 图片将仅被压缩。 2. 转换 WebP 并…...
《Vue.js》阅读之响应式数据与副作用函数
Vue.js 《Vue.js设计与实现》(霍春阳) 适合:从零手写Vue3响应式系统,大厂面试源码题直接覆盖。重点章节:第4章(响应式)、第5章(渲染器)、第8章(编译器&…...

如何应对网站被爬虫和采集?综合防护策略与实用方案
在互联网时代,网站内容被恶意爬虫或采集工具窃取已成为常见问题。这不仅侵犯原创权益,还可能影响网站性能和SEO排名。以下是结合技术、策略与法律的综合解决方案,帮助网站构建有效防护体系。 一、技术防护:阻断爬虫的“技术防线”…...

AI智慧公园管理方案:用科技重塑市民的“夜游体验”
AI智慧公园管理方案:多场景智能巡检与安全防控 一、背景与痛点分析 夏季夜间,公园成为市民休闲娱乐的核心场所,但管理难度随之激增: 宠物管理失控:未牵绳宠物进入园区,随地排泄、惊扰游客,甚…...
学习日志04 java
PTA上的练习复盘 java01 编程题作业感悟: 可以用ai指导自己怎么调试,但是不要把调代码这过程里面的精华交给ai,就是自己去修正错误不能让ai代劳!~~~ 1 scanner.close() Scanner *** new Scanner(System.in); ***.close(); …...

LVGL- 按钮矩阵控件
1 按钮矩阵控件 lv_btnmatrix 是 LVGL(Light and Versatile Graphics Library) v8 中提供的一个非常实用的控件,用于创建带有多个按钮的矩阵布局。它常用于实现虚拟键盘、数字键盘、操作面板、选择菜单等场景,特别适用于嵌入式设…...
【node】6 包与npm
前言 目标 1 了解什么是包 2 怎么使用npm下载包 #mermaid-svg-Ur0d2uCdQeAQOJjW {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-Ur0d2uCdQeAQOJjW .error-icon{fill:#552222;}#mermaid-svg-Ur0d2uCdQeAQOJjW .erro…...

1. 使用 IntelliJ IDEA 创建 React 项目:创建 React 项目界面详解;配置 Yarn 为包管理器
1. 使用 IntelliJ IDEA 创建 React 项目:创建 React 项目界面详解;配置 Yarn 为包管理器 🧩 使用 IntelliJ IDEA 创建 React 项目(附 Yarn 配置与 Vite 建议)📷 创建 React 项目界面详解1️⃣ Name…...
T-SQL在SQL Server中判断表、字段、索引、视图、触发器、Synonym等是否存在
SQL Server创建或者删除表、字段、索引、视图、触发器前判断是否存在。 目录 1. SQL Server创建表之前判断表是否存在 2. SQL Server新增字段之前判断是否存在 3. SQL Server删除字段之前判断是否存在 4. SQL Server新增索引之前判断是否存在 5. SQL Server判断视图是否存…...
Docker中mysql镜像保存与导入
一、Docker中mysql镜像保存 Docker 的 MySQL 镜像保存通常有两种场景:一种是保存镜像本身的修改(如配置、初始化数据),另一种是持久化保存容器运行时产生的数据(如数据库表、用户数据)。以下是具体方法&am…...

【JVM】从零开始深度解析JVM
本篇博客给大家带来的是JVM的知识点, 重点在类加载和垃圾回收机制上. 🐎文章专栏: JavaEE初阶 🚀若有问题 评论区见 ❤ 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条. 你们的支持是我不断创作的动力 . 王子,公主请阅🚀 …...

算法训练营第十四天|110. 平衡二叉树、257. 二叉树的所有路径、404. 左叶子之和、222.完全二叉树的节点个数
110.平衡二叉树 题目 思路与解法 # Definition for a binary tree node. # class TreeNode: # def __init__(self, val0, leftNone, rightNone): # self.val val # self.left left # self.right right class Solution:def isBalanced(self, r…...
Java单例模式总结
说明:单例模式的核心是确保一个类只有一个实例,并提供全局访问点。饿汉式和懒汉式是两种常见的实现方式 一、饿汉式和懒汉式 1. 饿汉式(Eager Initialization) public class EagerSingleton {// 类加载时直接初始化实例private…...

在 Elasticsearch 中删除文档中的某个字段
作者:来自 Elastic Kofi Bartlett 探索在 Elasticsearch 中删除文档字段的方法。 更多有关 Elasticsearch 文档的操作,请详细阅读文章 “开始使用 Elasticsearch (1)”。 想获得 Elastic 认证?查看下一期 Elasticsear…...
OpenCV中适用华为昇腾(Ascend)后端的逐元素操作(Per-element Operations)
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 针对华为昇腾(Ascend)后端的逐元素操作(Per-element Operations),这些操作通常用于图…...
Jenkins集成Maven
一、概述 Jenkins是一个开源的持续集成工具,用于自动化各种开发任务。Maven是一个项目管理和构建自动化工具,主要用于Java项目。通过将Jenkins和Maven集成,可以实现自动化构建、测试和部署,提高开发效率和代码质量。 二、前提条…...

初识Linux · TCP基本使用 · 回显服务器
目录 前言: 回显服务器 TCPserver_v0 TCPserver_v1--多进程版本 TCPserver_v2--多线程版本 前言: 前文我们介绍了UDP的基本使用,本文我们介绍TCP的基本使用,不过TCP的使用我们这里先做一个预热,即只是使用TCP的A…...
Qwen:Qwen3,R1 在 Text2SQL 效果评估
【对比模型】 Qwen3 235B-A22B(2350亿总参数,220亿激活参数),32B,30B-A3B;QwQ 32B(推理模型)DeepSeek-R1 671B(满血版)(推理模型) 1&a…...

【layout组件 与 路由镶嵌】vue3 后台管理系统
前言 很多同学在第一次搭建后台管理系统时,会遇到一个问题,layout组件该放哪里?如何使用?路由又该如何设计? 这边会讲一下我的思考过程和最后的结果,大家可以参考一下,希望大家看完能有所收获。…...

mobile自动化测试-appium webdriverio
WebdriverIO是一款支持mobile app和mobile web自动化测试框架,与appium集成,完成对mobile应用测试。支持ios 和android两种平台,且功能丰富,是mobile app自动化测试首选框架。且官方还提供了mobile 应用测试example代码࿰…...