原子对象和原子操作​

原子对象和原子操作 ​原子对象和原子操作是 C11 标准引入的重要特性,主要用于多线程编程中的同步操作,可以保证对共享变量的操作是原子的,避免数据竞争。

为什么需要原子类型 ​原子类型解决的是「并发访问同一对象时的数据竞争」问题。多个线程如果同时读写普通对象而没有同步,行为是未定义的;把对象声明为原子类型后,读写会以原子语义进行,不会发生撕裂访问。C11 在 头文件中定义了原子类型,并提供了一组配套的原子操作函数。

原子类型 ​最常用的原子类型包括:

catomic_bool // bool 的原子版本

atomic_char // char 的原子版本

atomic_int // int 的原子版本

atomic_uint // unsigned int 的原子版本

atomic_long // long 的原子版本

atomic_ulong // unsigned long 的原子版本

atomic_size_t // size_t 的原子版本1234567也可以使用 _Atomic 关键字将任意类型转换为其原子版本:

c_Atomic int counter; // 声明原子整型对象1atomic_int 这类名字本质是标准库提供的便捷类型别名,而 _Atomic(T) 是语言层构造。两者语义一致,选择哪种通常取决于代码风格。

原子操作 ​基本原子操作 ​注:以下函数是为所有的原子类型 A 定义的泛型函数:类型 C 为 A 对应的非原子类型。

原子存储和加载:

cvoid atomic_store(volatile A* obj, C desired); // 原子存储(原子写)

C atomic_load(const volatile A* obj); // 原子加载(原子读)12上面两个函数默认以 memory_order_seq_cst 内存序执行读写操作。

这两个函数有对应的 _explicit 版本,可以指定内存序:

cvoid atomic_store_explicit(volatile A* obj, C desired, memory_order order);

C atomic_load_explicit(const volatile A* obj, memory_order order);12atomic_load_explicit 指定的内存序只能是 memory_order_acquire、memory_order_relaxed、memory_order_consume 或 memory_order_seq_cst;atomic_store_explicit 指定的内存序只能是 memory_order_release、memory_order_relaxed 或 memory_order_seq_cst。示例:

catomic_int counter = 0;

atomic_store_explicit(&counter, 1, memory_order_release);

int value = atomic_load_explicit(&counter, memory_order_acquire);123原子交换:

cC atomic_exchange(volatile A* obj, C desired); // 原子交换1原子比较与交换:

cbool atomic_compare_exchange_strong(volatile A* obj,

C* expected,

C desired);

bool atomic_compare_exchange_weak(volatile A* obj,

C* expected,

C desired);

bool atomic_compare_exchange_weak_explicit(volatile A* obj,

C* expected,

C desired,

memory_order success,

memory_order failure);

bool atomic_compare_exchange_strong_explicit(volatile A* obj,

C* expected,

C desired,

memory_order success,

memory_order failure);12345678910111213141516原子算术操作 ​注:以下函数是为所有的原子类型 A 定义的泛型函数:类型 C 为 A 对应的非原子类型;如果 A 为原子整数类型,则类型 M 为 A 对应的非原子类型;如果 A 为原子指针类型,则类型 M 为 ptrdiff_t。

c// 原子加法

C atomic_fetch_add(volatile A* obj, M arg);

// 原子减法

M atomic_fetch_sub(volatile A* obj, M arg);

// 原子与运算

C atomic_fetch_and(volatile A* obj, M arg);

// 原子或运算

C atomic_fetch_or(volatile A* obj, M arg);

// 原子异或运算

C atomic_fetch_xor(volatile A* obj, M arg);1234567891011121314内存序 ​原子操作可以指定内存序(memory order)来控制操作的顺序:

cenum memory_order {

memory_order_relaxed, // 最宽松的内存序

memory_order_consume, // 消费序

memory_order_acquire, // 获取序

memory_order_release, // 释放序

memory_order_acq_rel, // 获取释放序

memory_order_seq_cst // 顺序一致性(默认)

};12345678示例:

catomic_int counter = 0;

// 使用指定的内存序进行原子操作

atomic_store_explicit(&counter, 1, memory_order_release);

int value = atomic_load_explicit(&counter, memory_order_acquire);12345使用示例 ​一个使用原子操作的简单计数器示例:

c#include

#include

#include

atomic_int counter = 0;

int thread_func(void* arg) {

for (int i = 0; i < 1000000; i++) {

atomic_fetch_add(&counter, 1);

}

return 0;

}

int main() {

thrd_t th1, th2;

// 创建两个线程

thrd_create(&th1, thread_func, NULL);

thrd_create(&th2, thread_func, NULL);

// 等待线程结束

thrd_join(th1, NULL);

thrd_join(th2, NULL);

printf("Final counter value: %d\n", atomic_load(&counter));

return 0;

}123456789101112131415161718192021222324252627可能的输出(示例):

bash<输出与输入或平台相关,请以实际运行为准>

使用建议 ​原子类型适合计数器、状态位、无锁队列节点标志等细粒度同步场景;涉及多个对象的一致性更新时,互斥锁通常更容易写对。优先写出可证明正确的同步模型,再考虑性能微调。

Copyright © 2088 霓蓝星游戏活动站_二次元游戏资讯_专属礼包 All Rights Reserved.
友情链接