当前位置: 首页 > news >正文

C语言原子操作的实现示例

原子操作是并发编程中的一个核心概念。让我详细解释:

什么是原子操作?

原子操作是指在执行过程中不会被中断的操作,要么完全执行,要么完全不执行,不会出现部分执行的状态。

比喻理解

就像原子是不可分割的基本单位一样,原子操作是不可分割的操作单位。

非原子操作的问题

先看一个非原子操作的例子:

1

2

3

4

5

6

intcounter = 0;

// 这不是原子操作!

voidincrement() {

counter = counter + 1;

}

在汇编层面,这通常分为三步:

1

2

3

mov eax, [counter] ; 1. 读取counter到寄存器

inc eax ; 2. 寄存器值加1

mov [counter], eax ; 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

#include <stdatomic.h>

// 声明原子变量

atomic_int atomic_counter = ATOMIC_VAR_INIT(0);

// 原子操作

voidincrement_atomic() {

atomic_fetch_add(&atomic_counter, 1);// 原子加法

}

intmain() {

atomic_counter = 5;// 原子存储

intvalue = atomic_counter;// 原子加载

printf("Counter: %d\n", value);

return0;

}

常见的原子操作函数

基本操作

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

#include <stdatomic.h>

atomic_int counter = ATOMIC_VAR_INIT(0);

// 加载和存储

intload_value = atomic_load(&counter);// 原子读取

atomic_store(&counter, 42);// 原子写入

// 交换操作

intold_value = atomic_exchange(&counter, 100);// 原子交换

// 比较交换(CAS - Compare And Swap)

intexpected = 100;

if(atomic_compare_exchange_strong(&counter, &expected, 200)) {

printf("CAS成功: 旧值=%d, 新值=200\n", expected);

}

算术运算

1

2

3

4

5

6

7

8

9

// 原子加法

intold = atomic_fetch_add(&counter, 5);// counter += 5,返回旧值

// 原子减法

atomic_fetch_sub(&counter, 3);// counter -= 3

// 原子自增/自减

atomic_fetch_add(&counter, 1);// counter++

atomic_fetch_sub(&counter, 1);// counter--

位运算

1

2

3

4

5

6

atomic_int flags = ATOMIC_VAR_INIT(0);

// 原子位操作

atomic_fetch_or(&flags, 0x01);// flags |= 0x01

atomic_fetch_and(&flags, ~0x01);// flags &= ~0x01

atomic_fetch_xor(&flags, 0x03);// flags ^= 0x03

原子操作的实际例子

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

#include <stdatomic.h>

#include <pthread.h>

#include <stdio.h>

atomic_int counter = ATOMIC_VAR_INIT(0);

void* worker(void* arg) {

for(inti = 0; i < 100000; i++) {

atomic_fetch_add(&counter, 1);// 原子自增

}

returnNULL;

}

intmain() {

pthread_t t1, t2;

pthread_create(&t1, NULL, worker, NULL);

pthread_create(&t2, NULL, worker, NULL);

pthread_join(t1, NULL);

pthread_join(t2, NULL);

printf("最终计数: %d (应该是200000)\n", atomic_load(&counter));

return0;

}

2. 自旋锁实现

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

#include <stdatomic.h>

typedefatomic_flag spinlock_t;

voidspinlock_init(spinlock_t* lock) {

atomic_flag_clear(lock);

}

voidspinlock_lock(spinlock_t* lock) {

// 忙等待,直到获得锁

while(atomic_flag_test_and_set(lock)) {

// 可选的:减少CPU占用

// __builtin_ia32_pause(); // x86的PAUSE指令

}

}

voidspinlock_unlock(spinlock_t* lock) {

atomic_flag_clear(lock);

}

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

#include <stdatomic.h>

#include <stdlib.h>

typedefstructNode {

intdata;

structNode* next;

} Node;

typedefstruct{

_Atomic(Node*) top;

} LockFreeStack;

voidstack_init(LockFreeStack* stack) {

atomic_store(&stack->top, NULL);

}

voidstack_push(LockFreeStack* stack,intvalue) {

Node* new_node =malloc(sizeof(Node));

new_node->data = value;

Node* old_top;

do{

old_top = atomic_load(&stack->top);

new_node->next = old_top;

}while(!atomic_compare_exchange_weak(&stack->top, &old_top, new_node));

}

intstack_pop(LockFreeStack* stack) {

Node* old_top;

Node* new_top;

do{

old_top = atomic_load(&stack->top);

if(old_top == NULL)return-1;// 栈空

new_top = old_top->next;

}while(!atomic_compare_exchange_weak(&stack->top, &old_top, new_top));

intvalue = old_top->data;

free(old_top);

returnvalue;

}

内存顺序(Memory Order)

原子操作还涉及内存可见性问题:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

#include <stdatomic.h>

atomic_int data = ATOMIC_VAR_INIT(0);

atomic_int flag = ATOMIC_VAR_INIT(0);

// 生产者线程

voidproducer() {

atomic_store_explicit(&data, 42, memory_order_relaxed);

atomic_store_explicit(&flag, 1, memory_order_release);// 释放语义

}

// 消费者线程

voidconsumer() {

while(atomic_load_explicit(&flag, memory_order_acquire) == 0) {

// 等待

}

intvalue = atomic_load_explicit(&data, memory_order_relaxed);

printf("Data: %d\n", value);// 保证看到42

}

不同平台的原生原子操作

x86架构

1

2

3

4

5

6

7

8

9

10

// 内联汇编实现原子操作

intatomic_increment(int* value) {

__asm__ __volatile__(

"lock incl %0"// lock前缀确保原子性

:"+m"(*value)

:

:"cc"

);

return*value;

}

GCC内置原子操作

1

2

3

4

5

6

7

8

9

10

intcounter = 0;

// GCC内置的原子操作

voidincrement_gcc() {

__sync_fetch_and_add(&counter, 1);

}

intcompare_and_swap_gcc(int* ptr,intoldval,intnewval) {

return__sync_val_compare_and_swap(ptr, oldval, newval);

}

原子操作的优缺点

优点:

  • 高性能:避免锁的开销
  • 无死锁:不会出现锁顺序问题
  • 可扩展性:在多核系统中表现良好

缺点:

  • 复杂性:正确实现很困难
  • ABA问题:在CAS操作中可能出现
  • 平台依赖性:不同硬件支持程度不同
http://www.jsqmd.com/news/1111893/

相关文章:

  • Python密钥管理实战:从生成到销毁的全生命周期安全指南
  • Pytest API测试进阶:断言策略与插件生态实战指南
  • AURA:面向实时交互的时空决策引擎设计与工程实践
  • OAuth2.0授权码模式中CSRF攻击的防御:state参数与PKCE实战指南
  • 零基础转行AI Agent工程师:35岁成功转型实战指南
  • 终极免费指南:3分钟掌握Montserrat字体家族的完整使用技巧
  • 佳能mg3180故障灯交替闪烁7次,什么故障?别慌,这是提示你要清零了,自己在家就可以修好了,别花100多给维修店维修了,我用佳能V6.200原版清零软件2分钟修好了,直接省了100多块,亲测完美。
  • Nmap渗透测试实战指南:从网络扫描到漏洞定位的完整流程
  • JavaScript面试题自动化测试:从手动验证到工程化实践的完整方案
  • Hutool RSA实战:Java非对称加密与数字签名完整指南
  • Kali渗透测试网络配置:桥接与NAT模式实战选择指南
  • 智能散热系统设计:DRV8213驱动与PIC24单片机控制
  • 应急响应实战:从百万行代码中高效定位与清除隐蔽后门
  • 基于DRV8213的智能温控风扇系统设计与优化
  • Trivy漏洞扫描精准配置与修复策略实战指南
  • 高效漏洞通报:精炼模板与实战话术设计指南
  • 鸿蒙NEXT应用开发:基于证书的RSA公钥加密实战指南
  • 从零搭建Python Selenium自动化测试框架:POM设计与Pytest实践
  • 智能散热管理系统设计与DRV8213电机驱动器应用
  • 终极免费离线启动器:PrismLauncher-Cracked完全解锁Minecraft离线账户功能指南
  • Kali Linux与Metasploit实战:从信息收集到权限获取的完整渗透测试流程
  • PentestGPT:AI增强型渗透测试助手实战指南
  • Web安全入门:从SQL注入到XSS的攻防原理与实战指南
  • 5步攻克res-downloader证书验证与反爬拦截实战指南
  • Kiran-shell 社区贡献指南:如何参与开源桌面面板项目开发
  • 从零构建Python接口自动化测试框架:统一封装与数据驱动实战
  • 实战指南:利用BurpSuite检测与修复Apache/Tomcat的TRACE方法漏洞
  • AES加密实战指南:从原理到跨平台实现与安全加固
  • 彻底告别网盘下载限制:八大平台真实链接一键获取完整指南
  • 仿勒索锁屏病毒应急响应:从识别到清除的实战指南