C语言原子操作的实现示例
原子操作是并发编程中的一个核心概念。让我详细解释:
什么是原子操作?
原子操作是指在执行过程中不会被中断的操作,要么完全执行,要么完全不执行,不会出现部分执行的状态。
比喻理解
就像原子是不可分割的基本单位一样,原子操作是不可分割的操作单位。
非原子操作的问题
先看一个非原子操作的例子:
1 2 3 4 5 6 |
|
在汇编层面,这通常分为三步:
1 2 3 |
|
竞态条件问题:
线程A:读取counter=0
线程B:读取counter=0
线程A:计算0+1=1
线程B:计算0+1=1
线程A:写入counter=1
线程B:写入counter=1 ← 结果应该是2,但实际是1!
C语言中的原子操作
C11标准引入的原子类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
常见的原子操作函数
基本操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
算术运算
1 2 3 4 5 6 7 8 9 |
|
位运算
1 2 3 4 5 6 |
|
原子操作的实际例子
1. 无锁计数器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
2. 自旋锁实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
3. 无锁栈(Lock-Free Stack)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
|
内存顺序(Memory Order)
原子操作还涉及内存可见性问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
不同平台的原生原子操作
x86架构
1 2 3 4 5 6 7 8 9 10 |
|
GCC内置原子操作
1 2 3 4 5 6 7 8 9 10 |
|
原子操作的优缺点
优点:
- 高性能:避免锁的开销
- 无死锁:不会出现锁顺序问题
- 可扩展性:在多核系统中表现良好
缺点:
- 复杂性:正确实现很困难
- ABA问题:在CAS操作中可能出现
- 平台依赖性:不同硬件支持程度不同
