c++如何使用std::atomic原子操作_c++ 无锁编程基础与并发冲突解决【方法】
技术百科
尼克
发布时间:2026-01-01
浏览: 次 std::atomic 禁止拷贝构造和赋值以保障原子性,必须用 load/store 或 fetch_add/compare_exchange 等原子操作;compare_exchange_weak 因伪失败更高效,推荐循环使用;内存序需按需选择,错用易致数据竞争;T 需 trivially copyable 且尺寸适配,否则退化为加锁。
std::atomic 为什么不能直接赋值或拷贝
因为 std::atomic 禁止了拷贝构造和拷贝赋值操作符,这是为保证原子性不被意外破坏。试图写 std::atomic 或 auto c = a; 会触发编译错误:use of deleted function。
- 必须用
.load()读取当前值(可指定内存序) - 必须用
.store(x)写入新值(同样支持内存序) - 需要“读-改-写”时,优先用
.fetch_add()、.compare_exchange_weak()等原子成员函数
compare_exchange_weak 和 compare_exchange_strong 怎么选
两者都实现 CAS(Compare-and-Swap),但 compare_exchange_weak 允许伪失败(spurious failure):即使预期值匹配,也可能返回 false。这在某些平台(如 x86 上少见,ARM 上较常见)由底层指令限制导致。
- 循环中使用时,
weak版本通常性能更好,推荐作为默认选择 -
strong版本保证“值不匹配才失败”,适合不能容忍重试逻辑的场景(如单次尝试关键路径) - 务必配合 do-while 循环使用,避免漏掉失败重试
std::atomiccounter{0}; int expected = counter.load(); do { int desired = expected + 1; } while (!counter.compare_exchange_weak(expected, desired));
内存序(memory order)不是可有可无的配置项
省略内存序参数(如只写 a.store(42))等价于 a.store(42, std::memory_order_seq,即最强一致性。但多数场景不需要这么重的同步开销。
_cst)
-
std::memory_order_relaxed:仅保证原子性,不约束前后内存访问顺序 —— 计数器、标志位常用 -
std::memory_order_acquire:用于读操作,确保之后的读/写不被重排到它前面 -
std::memory_order_release:用于写操作,确保之前的读/写不被重排到它后面 - acquire-release 配对可实现线程间同步,而无需全局顺序
错用内存序不会报错,但可能引发极难复现的数据竞争 —— 比如把 relaxed 误用于需同步的 flag 变量,会导致另一线程看到“部分初始化”的对象。
std::atomic 对 T 的类型要求很实际
并非所有类型都能套 std::atomic。编译期会检查 T 是否为 trivially copyable,且大小不能超过平台支持的原子指令宽度(通常 ≤ 16 字节,x86-64 下一般 ≤ 8 字节)。
- 基本类型(
int、long long、指针)基本都 OK - 自定义结构体只有满足
std::is_trivially_copyable_v且不含虚函数、非平凡构造/析构时,才可能被接受 - 即使满足条件,若尺寸过大(如 32 字节 struct),GCC/Clang 会退化为内部加锁实现 —— 此时已不是“无锁”,且性能下降明显
- 不确定时,用
static_assert(std::atomic显式校验::is_always_lock_free)
无锁编程真正的门槛不在语法,而在对共享状态变更边界的精确刻画。一个 std::atomic_flag 能安全自旋,但若把它和非原子字段混在同一缓存行里,就可能因 false sharing 拖垮性能 —— 这类问题不会报错,只会让多核跑得比单核还慢。
# ai
# 这是
# 把它
# 都能
# 不需要
# 不被
# auto
# 循环
# 并发
# 对象
# c++
# int
# 字节
# 指针
# 报错
# 为什么
# 线程
# function
# red
# 无锁
# 重试
# 成员函数
# 结构体
# while
# Struct
# 虚函数
# 加锁
# 编译错误
# 多核
# 到它
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Mac如何修复应用程序权限问题_Mac磁盘工具修复
- PythonDocker高级项目部署教程_多容器管
- PowerShell怎么创建复杂的XML结构
- php中::能用于接口静态方法吗_接口静态方法调用
- Win11怎么恢复出厂设置_Win11重置此电脑保
- Windows蓝屏BAD_POOL_HEADER故
- Mac如何开启夜览模式_Mac护眼模式设置与定时
- c++中如何使用auto关键字_c++11类型推导
- Win11时间不对怎么同步_Win11自动校准互联
- php怎么捕获异常_trycatch结构处理运行时
- Win10如何卸载自带Edge_Win10彻底卸载
- Python项目维护经验_长期演进说明【指导】
- Win11怎么设置默认PDF阅读器 Win11修改
- Win11怎么关闭VBS安全性_Windows11
- 微信JSAPI支付回调PHP怎么接收_处理JSAP
- Django密码修改后会话失效的解决方案
- Laravel 查询 JSON 列:高效筛选包含数
- Win10电脑C盘红了怎么清理_Windows10
- php订单日志怎么在swoole写_php协程sw
- Win11如何设置开机自动联网 Win11宽带连接
- C++如何获取CPU核心数?(std::threa
- Win11怎么查看已连接wifi密码 Win11查
- Win11怎么开启自动HDR画质_Windows1
- Golang如何避免指针逃逸_Golang逃逸分析
- 如何用正则表达式精确匹配“start”到“end”
- Win11开机速度慢怎么优化_Win11系统启动加
- php485在macos下怎么配置_php485
- PHP 中 require() 语句返回值的用法详
- Python实现图数据库操作_Neo4j核心CRU
- Mac怎么设置登录项_Mac管理开机自启动程序【教
- Windows10系统怎么查看系统版本_Win10
- PHP的FastAdmin架构适合二次开发吗_特点
- Win11开机Logo怎么换_Win11自定义启动
- c++怎么使用类型萃取type_traits_c+
- Win11如何关闭游戏模式 Win11禁用Xbox
- 如何使用Golang捕获测试日志_Golang t
- php下载安装选zip还是msi格式_两种安装包对
- php后缀怎么变mp4能播放_让php伪装mp4正
- Win11怎么更改计算机名_Windows11系统
- Windows 10自带杀毒软件在哪_Window
- Win10系统字体模糊怎么办_Windows10高
- 如何在Golang中实现基础配置管理功能_Gola
- Windows 11无法安全删除U盘提示设备正在使
- Win11怎样安装微信开发者工具_Win11安装开
- Win11笔记本怎么看电池健康度_Win11电池报
- Win10如何更改电脑休眠时间_Windows10
- Win11怎么更改电脑名称_Windows 11修
- Windows怎样关闭锁屏广告_Windows关闭
- Win11怎么自动隐藏任务栏_Win11全屏显示设
- 如何在Golang中解压文件_Golang com

QQ客服