原子类型
C11 标准在 <stdatomic.h> 头文件中定义了原子类型。最常用的原子类型包括:
c
atomic_bool // bool 的原子版本
atomic_char // char 的原子版本
atomic_int // int 的原子版本
atomic_uint // unsigned int 的原子版本
atomic_long // long 的原子版本
atomic_ulong // unsigned long 的原子版本
atomic_size_t // size_t 的原子版本1
2
3
4
5
6
7
2
3
4
5
6
7
运行结果:该代码块主要用于语法或结构说明,单独运行通常无终端输出。
也可以使用 _Atomic 关键字将任意类型转换为其原子版本:
c
_Atomic int counter; // 声明原子整型对象1
运行结果:该代码块主要用于语法或结构说明,单独运行通常无终端输出。
原子类型解决的是“并发访问同一对象时的数据竞争”问题。多个线程如果同时读写普通对象而没有同步,行为是未定义的;把对象声明为原子类型后,读写会以原子语义进行,不会发生撕裂访问。
1. 基本读写
c
#include <stdatomic.h>
atomic_int counter = 0;
void inc(void) {
atomic_fetch_add(&counter, 1);
}1
2
3
4
5
6
7
2
3
4
5
6
7
运行结果:该代码块主要用于语法或结构说明,单独运行通常无终端输出。
上例中的 atomic_fetch_add 是读-改-写原子操作,可安全用于并发计数。
2. 与 _Atomic 关键字的关系
atomic_int 这类名字本质是标准库提供的便捷类型别名,而 _Atomic(T) 是语言层构造。两者语义一致,选择哪种通常取决于代码风格。
c
_Atomic unsigned long total = 0;1
运行结果:该代码块主要用于语法或结构说明,单独运行通常无终端输出。
3. 内存序
原子操作除了“原子性”,还涉及“可见性顺序”。默认内存序通常是 memory_order_seq_cst,语义最强、最直观。若需要更细粒度控制,可使用 _explicit 版本并指定 memory_order_relaxed、memory_order_acquire、memory_order_release 等。
c
atomic_store_explicit(&counter, 1, memory_order_release);
int x = atomic_load_explicit(&counter, memory_order_acquire);1
2
2
运行结果:该代码块主要用于语法或结构说明,单独运行通常无终端输出。
内存序细节会在并发章节进一步展开;这里先记住:内存序越弱,性能潜力越高,但正确性证明也越复杂。
4. 使用建议
原子类型适合计数器、状态位、无锁队列节点标志等细粒度同步场景;涉及多个对象的一致性更新时,互斥锁通常更容易写对。优先写出可证明正确的同步模型,再考虑性能微调。