系统编程基础

C语言原子量的使用

在C语言中,原子量(Atomic)用于实现多线程环境下的无锁同步操作,确保对共享变量的操作是不可分割的(即原子性)。C11标准引入了 <stdatomic.h> 头文件,提供了对原子操作的支持。
互斥量用于保护多行代码块,原子量可以保护一行代码(对原子变量的操作)。以下是原子量的核心用法和注意事项:


1. 原子类型声明

使用 _Atomic 修饰符声明原子变量:

#include <stdatomic.h>

_Atomic int counter = ATOMIC_VAR_INIT(0); // 声明并初始化为0

或简写:

atomic_int counter = 0; // 等效于 _Atomic int

2. 基本原子操作

加载(Load)和存储(Store)

int value;
value = atomic_load(&counter);        // 原子读取
atomic_store(&counter, 42);          // 原子写入

交换(Exchange)

int old = atomic_exchange(&counter, 100); // 将counter设为100,返回旧值

比较并交换(CAS, Compare-And-Swap)

int expected = 10;
int desired = 20;
if (atomic_compare_exchange_strong(&counter, &expected, desired)) {
    // 成功:counter原值为expected,被更新为desired
} else {
    // 失败:counter当前值 != expected,expected被更新为实际值
}

3. 原子算术/位运算

atomic_fetch_add(&counter, 5);    // 原子加5,返回旧值
atomic_fetch_sub(&counter, 3);    // 原子减3
atomic_fetch_or(&counter, 0x1);   // 原子按位或
atomic_fetch_and(&counter, ~0x1); // 原子按位与

4. 内存顺序(Memory Order)

指定原子操作的内存同步行为,控制指令重排和可见性:

atomic_store_explicit(&counter, 42, memory_order_release); // 写入释放
int val = atomic_load_explicit(&counter, memory_order_acquire); // 读取获取

常用选项:
memory_order_relaxed:仅保证原子性,无同步/顺序约束。
memory_order_acquire:本操作前的所有读写不会被重排到它之后。
memory_order_release:本操作后的所有读写不会被重排到它之前。
memory_order_seq_cst:严格顺序一致性(默认)。


5. 示例:线程安全的计数器

#include <stdatomic.h>
#include <stdio.h>
#include <threads.h>

atomic_int counter = 0;

int thread_func(void *arg) {
    for (int i = 0; i < 10000; i++) {
        atomic_fetch_add(&counter, 1);
    }
    return 0;
}

int main() {
    thrd_t t1, t2;
    thrd_create(&t1, thread_func, NULL);
    thrd_create(&t2, thread_func, NULL);
    thrd_join(t1, NULL);
    thrd_join(t2, NULL);
    printf("Counter: %d\n", counter); // 正确输出20000
    return 0;
}

6. 注意事项

  1. 性能:原子操作比普通操作慢,仅在必要时使用。
  2. 适用场景:简单共享变量(如标志、计数器),复杂逻辑仍需互斥锁。
  3. 兼容性:需C11及以上编译器(如GCC -std=c11)。
  4. 避免ABA问题:CAS操作需注意值被其他线程多次修改的情况。

7. 扩展知识

无锁编程:原子量是实现无锁数据结构的基础(如队列、栈)。
编译器屏障atomic_signal_fence() 用于线程与信号处理函数间的同步。

通过合理使用原子量,可以高效解决多线程竞争问题,但需谨慎设计以避免逻辑错误。

回复

This is just a placeholder img.