0

0

如何使用c++20的std::atomic_ref对结构体成员进行原子操作? (细粒度同步)

冰火之心

冰火之心

发布时间:2026-01-14 09:59:31

|

315人浏览过

|

来源于php中文网

原创

std::atomic_ref要求对象可平凡复制且地址按类型对齐,否则未定义;禁止用于位域、临时对象、const/volatile成员及非平凡类型;需配合memory_order保证同步语义;适用共享内存等零成本场景。

如何使用c++20的std::atomic_ref对结构体成员进行原子操作? (细粒度同步)

std::atomic_ref 要求对象必须是可平凡复制(trivially copyable)且对齐满足要求

直接对结构体成员(比如 struct S { int a; double b; }; S s; 中的 s.a)构造 std::atomic_ref 是可行的,但前提是该成员地址必须满足 alignof(int) 对齐。C++20 标准明确要求:被引用的对象地址必须至少按其类型对齐,否则行为未定义。

常见陷阱是结构体内存布局导致成员未对齐。例如:

struct BadAlign {
    char c;
    int a; // 在多数平台上,&a 的地址可能不是 4 字节对齐(因前面有 1 字节 char)
};
BadAlign x{};
std::atomic_ref ref{x.a}; // ❌ 未定义行为:x.a 地址可能不对齐

解决方法

  • alignas 强制结构体或成员对齐:struct GoodAlign { char c; alignas(int) int a; };
  • 确保结构体本身按最大成员对齐(如加 alignas(alignof(int))
  • std::is_aligned(C++23)或手动检查地址:(reinterpret_cast(&x.a) % alignof(int)) == 0

不能对位域、引用、非静态成员指针或临时对象使用 std::atomic_ref

std::atomic_ref 只接受左值引用,且该左值必须指向生命周期足够长、内存稳定的对象。结构体中的位域(如 int flag : 1;)没有独立地址,无法取址,因此 std::atomic_ref{s.flag} 编译失败 —— 错误信息通常是 "taking address of bit-field"

立即学习C++免费学习笔记(深入)”;

其他不合法场景包括:

  • std::atomic_ref{s.member},其中 memberconstvolatile 限定的(除非 atomic_ref 模板参数也带相同限定)
  • 对结构体临时对象的成员取引用:std::atomic_ref{S{}.a} —— 绑定到临时对象,析构后引用悬空
  • 成员是 std::string 或含虚函数的类类型 —— 不满足 std::is_trivially_copyable_v,编译报错

细粒度同步需配合 memory_order 显式控制,避免意外重排

对结构体不同成员分别使用 std::atomic_ref,看似隔离,但 CPU 和编译器仍可能重排访问。例如两个线程分别更新 s.xs.y,若都用 memory_order_relaxed,则无法保证其他线程看到一致的修改顺序。

Baklib
Baklib

在线创建产品手册、知识库、帮助文档

下载

典型做法:

  • 读-改-写操作(如 fetch_add)默认用 memory_order_seq_cst,安全但开销大
  • 若需性能,且逻辑上允许弱序(如计数器、标志位),显式指定 memory_order_relaxedmemory_order_acquire/release
  • 跨成员的“组合语义”(如先写 s.ready = true 再写 s.data = 42)需用 memory_order_release + memory_order_acquire 配对,否则另一线程可能看到 ready==truedata 仍是旧值

示例:

struct Shared {
    alignas(int) int data;
    alignas(bool) bool ready;
};
Shared s{};

// 线程 A
std::atomic_ref{s.data}.store(42, std::memory_order_relaxed);
std::atomic_ref{s.ready}.store(true, std::memory_order_release); // release 同步点

// 线程 B
if (std::atomic_ref{s.ready}.load(std::memory_order_acquire)) { // acquire 匹配
    int d = std::atomic_ref{s.data}.load(std::memory_order_relaxed); // 此时 d 一定是 42
}

替代方案:std::atomic 与 std::atomic_ref 的权衡

如果结构体成员天然对齐、生命周期明确,std::atomic_ref 是零成本抽象 —— 它不增加存储开销,复用原有内存。但若频繁构造(如循环内每次取 ref),可能比直接用 std::atomic 成员略慢(因每次要检查对齐、生成原子指令前缀)。

更关键的区别在于所有权和初始化:

  • std::atomic 是值语义,自带初始化、析构,适合长期存在的原子变量
  • std::atomic_ref 是引用语义,不管理内存,适用于“已有数据,临时需要原子访问”的场景(如共享内存、内存映射文件、或 legacy 结构体无法修改定义时)
  • 若结构体定义可控,优先用 std::atomic 成员 —— 更安全、更直观、无需操心对齐

真正需要 std::atomic_ref 的典型场景,是对接 C 接口或硬件寄存器映射,其中内存布局固定且不可改。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

315

2023.08.02

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

521

2023.09.20

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

195

2025.06.09

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

187

2025.07.04

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

315

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

537

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

52

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

194

2025.08.29

php与html混编教程大全
php与html混编教程大全

本专题整合了php和html混编相关教程,阅读专题下面的文章了解更多详细内容。

12

2026.01.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 3.7万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号