#C 语言标准库头文件 stdatomic.h
这个头文件提供 原子操作 的相关功能。原子操作是指在并发环境中,一个不可分割的操作,它要么完全执行完毕,要么完全不执行,不会出现执行到一半被其他线程或进程打断的情况。
#示例
#include <stdio.h>
#include <stdatomic.h>
#include <threads.h> // C11 多线程标准头文件
atomic_int counter = 0; // 计数器,原子类型
// 线程函数,增加计数器
int increment(void* arg) {
int loops = *(int*)arg;
for (int i = 0; i < loops; i++) {
// 原子操作-加一
atomic_fetch_add(&counter, 1);
}
return 0;
}
int main(void) {
// 原子操作-比较交换:如果 counter 等于 expected,则将 counter 设为 10
int expected = 0;
if (atomic_compare_exchange_strong(&counter, &expected, 10)) {
printf("counter 的值是 0, 现在将其设为 10\n");
}
// 创建多个线程
thrd_t t1, t2;
int loops = 100000;
thrd_create(&t1, increment, &loops);
thrd_create(&t2, increment, &loops);
// 等待线程结束
thrd_join(t1, NULL);
thrd_join(t2, NULL);
printf("最终 counter 的值是: %d\n", atomic_load(&counter));
return 0;
}
运行结果:
counter 的值是 0, 现在将其设为 10 最终 counter 的值是: 200010
#类型
类型 | 标准 | 说明 |
---|---|---|
atomic_flag | C11 | 一个特殊的原子布尔类型,保证无锁但不提供加载或存储操 |
memory_order | C11 | 内存顺序 的枚举 |
#宏
宏 | 标准 | 说明 |
---|---|---|
ATOMIC_BOOL_LOCK_FREE | C11 | 表示 atomic_bool 类型的原子操作是否是无锁的,0 表示不是无锁,1 表示有时无锁,2表示始终无锁,下同 |
ATOMIC_CHAR_LOCK_FREE | C11 | 表示 atomic_char 类型的原子操作是否是无锁的 |
ATOMIC_CHAR8_T_LOCK_FREE | C23 | 表示 atomic_char8_t 类型的原子操作是否是无锁的 |
ATOMIC_CHAR16_T_LOCK_FREE | C11 | 表示 atomic_char16_t 类型的原子操作是否是无锁的 |
ATOMIC_CHAR32_T_LOCK_FREE | C11 | 表示 atomic_char32_t 类型的原子操作是否是无锁的 |
ATOMIC_WCHAR_T_LOCK_FREE | C11 | 表示 atomic_wchar_t 类型的原子操作是否是无锁的 |
ATOMIC_SHORT_LOCK_FREE | C11 | 表示 atomic_short 类型的原子操作是否是无锁的 |
ATOMIC_INT_LOCK_FREE | C11 | 表示 atomic_int 类型的原子操作是否是无锁的 |
ATOMIC_LONG_LOCK_FREE | C11 | 表示 atomic_long 类型的原子操作是否是无锁的 |
ATOMIC_LLONG_LOCK_FREE | C11 | 表示 atomic_llong 类型的原子操作是否是无锁的 |
ATOMIC_POINTER_LOCK_FREE | C11 | 表示指针类型的原子操作是否是无锁的 |
#函数
函数 | 标准 | 说明 |
---|---|---|
atomic_init | C11 | 初始化一个原子对象,并指定 内存顺序 |
ATOMIC_VAR_INIT | C11(在 C17 废弃) | 初始化一个原子变量,实际上直接赋值即可 |
ATOMIC_FLAG_INIT | C11 | 初始化一个 atomic_flag |
kill_dependency | C11 | 通知编译器 memory_order_consume 的原子操作不依赖某个值 |
atomic_thread_fence | C11 | 在当前线程插入一个 内存顺序 屏障 |
atomic_signal_fence | C11 | 在当前线程和信号处理程序之间插入一个 内存顺序 屏障 |
原子操作 | 标准 | 说明 |
---|---|---|
atomic_is_lock_free | C11 | 判断对象是否是无锁的 |
atomic_store | C11 | 原子地将值存入对象 |
atomic_load | C11 | 原子地读取对象 |
atomic_exchange | C11 | 原子地将值与对象交换 |
atomic_compare_exchange_weak | C11 | 原子地将值 A 与对象比较,如果相等则将值 B 与对象交换,可能虚假地失败,速度更快,常用于循环中 |
atomic_compare_exchange_strong | C11 | 原子地将值 A 与对象比较,如果相等则将值 B 与对象交换 |
atomic_fetch_add | C11 | 原子加法 |
atomic_fetch_sub | C11 | 原子减法 |
atomic_fetch_or | C11 | 原子地按位或 |
atomic_fetch_xor | C11 | 原子地按位异或 |
atomic_fetch_and | C11 | 原子地按位且 |
atomic_flag_test_and_set | C11 | 原子地将 atomic_flag 设为 true 并返回旧值 |
atomic_flag_clear | C11 | 原子地将 atomic_flag 设为 false |
指定内存顺序的原子操作 | 标准 | 说明 |
---|---|---|
atomic_store_explicit | C11 | 原子地将值存入对象 |
atomic_load_explicit | C11 | 原子地读取对象 |
atomic_exchange_explicit | C11 | 原子地将值与对象交换 |
atomic_compare_exchange_weak_explicit | C11 | 原子地将值 A 与对象比较,如果相等则将值 B 与对象交换,可能虚假地失败,速度更快,常用于循环中 |
atomic_compare_exchange_strong_explicit | C11 | 原子地将值 A 与对象比较,如果相等则将值 B 与对象交换 |
atomic_fetch_add_explicit | C11 | 原子加法 |
atomic_fetch_sub_explicit | C11 | 原子减法 |
atomic_fetch_or_explicit | C11 | 原子地按位或 |
atomic_fetch_xor_explicit | C11 | 原子地按位异或 |
atomic_fetch_and_explicit | C11 | 原子地按位且 |
atomic_flag_test_and_set_explicit | C11 | 原子地将 atomic_flag 设为 true 并返回旧值 |
atomic_flag_clear_explicit | C11 | 原子地将 atomic_flag 设为 false |
#内存顺序
内存顺序指定了原子操作如何影响其他线程的内存访问顺序。
内存顺序 | 标准 | 说明 |
---|---|---|
memory_order_relaxed | C11 | 仅保证本次操作的原子性,对其它内存操作没有约束 |
memory_order_consume | C11(在 C++ 26 废弃) | 仅保证数据依赖的顺序;通常退化为 memory_order_acquire |
memory_order_acquire | C11 | 保证读取当前原子变量之后的操作不会被重排到前面 |
memory_order_release | C11 | 保证写入当前原子变量之前的操作不会被重排到后面 |
memory_order_acq_rel | C11 | 组合 memory_order_acquire 和 memory_order_release |
memory_order_seq_cst | C11 | 一切按顺序执行,通常最慢,但最简单安全 |