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

C语言中原子操作(简要)

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

什么是原子操作?

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

比喻理解

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

非原子操作的问题

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

int counter = 0;// 这不是原子操作!
void increment() {counter = counter + 1;
}

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

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标准引入的原子类型

#include <stdatomic.h>// 声明原子变量
atomic_int atomic_counter = ATOMIC_VAR_INIT(0);// 原子操作
void increment_atomic() {atomic_fetch_add(&atomic_counter, 1);  // 原子加法
}int main() {atomic_counter = 5;                    // 原子存储int value = atomic_counter;            // 原子加载printf("Counter: %d\n", value);return 0;
}

常见的原子操作函数

基本操作

#include <stdatomic.h>atomic_int counter = ATOMIC_VAR_INIT(0);// 加载和存储
int load_value = atomic_load(&counter);        // 原子读取
atomic_store(&counter, 42);                    // 原子写入// 交换操作
int old_value = atomic_exchange(&counter, 100); // 原子交换// 比较交换(CAS - Compare And Swap)
int expected = 100;
if (atomic_compare_exchange_strong(&counter, &expected, 200)) {printf("CAS成功: 旧值=%d, 新值=200\n", expected);
}

算术运算

// 原子加法
int old = 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--

位运算

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. 无锁计数器

#include <stdatomic.h>
#include <pthread.h>
#include <stdio.h>atomic_int counter = ATOMIC_VAR_INIT(0);void* worker(void* arg) {for (int i = 0; i < 100000; i++) {atomic_fetch_add(&counter, 1);  // 原子自增}return NULL;
}int main() {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));return 0;
}

2. 自旋锁实现

#include <stdatomic.h>typedef atomic_flag spinlock_t;void spinlock_init(spinlock_t* lock) {atomic_flag_clear(lock);
}void spinlock_lock(spinlock_t* lock) {// 忙等待,直到获得锁while (atomic_flag_test_and_set(lock)) {// 可选的:减少CPU占用// __builtin_ia32_pause();  // x86的PAUSE指令}
}void spinlock_unlock(spinlock_t* lock) {atomic_flag_clear(lock);
}

3. 无锁栈(Lock-Free Stack)

#include <stdatomic.h>
#include <stdlib.h>typedef struct Node {int data;struct Node* next;
} Node;typedef struct {_Atomic(Node*) top;
} LockFreeStack;void stack_init(LockFreeStack* stack) {atomic_store(&stack->top, NULL);
}void stack_push(LockFreeStack* stack, int value) {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));
}int stack_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));int value = old_top->data;free(old_top);return value;
}

内存顺序(Memory Order)

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

#include <stdatomic.h>atomic_int data = ATOMIC_VAR_INIT(0);
atomic_int flag = ATOMIC_VAR_INIT(0);// 生产者线程
void producer() {atomic_store_explicit(&data, 42, memory_order_relaxed);atomic_store_explicit(&flag, 1, memory_order_release);  // 释放语义
}// 消费者线程
void consumer() {while (atomic_load_explicit(&flag, memory_order_acquire) == 0) {// 等待}int value = atomic_load_explicit(&data, memory_order_relaxed);printf("Data: %d\n", value);  // 保证看到42
}

不同平台的原生原子操作

x86架构

// 内联汇编实现原子操作
int atomic_increment(int* value) {__asm__ __volatile__("lock incl %0"          // lock前缀确保原子性: "+m" (*value):: "cc");return *value;
}

GCC内置原子操作

int counter = 0;// GCC内置的原子操作
void increment_gcc() {__sync_fetch_and_add(&counter, 1);
}int compare_and_swap_gcc(int* ptr, int oldval, int newval) {return __sync_val_compare_and_swap(ptr, oldval, newval);
}

原子操作的优缺点

优点:

  • 高性能:避免锁的开销

  • 无死锁:不会出现锁顺序问题

  • 可扩展性:在多核系统中表现良好

缺点:

  • 复杂性:正确实现很困难

  • ABA问题:在CAS操作中可能出现

  • 平台依赖性:不同硬件支持程度不同

原子操作 vs 互斥锁

特性原子操作互斥锁
性能高(硬件支持)中等(系统调用)
复杂度
适用场景简单操作(计数器、标志位)复杂临界区
死锁风险
可扩展性一般

总结

原子操作是:

  1. 不可分割的操作单位

  2. 线程安全的,无需额外同步

  3. 硬件支持的,通常通过CPU指令实现

  4. 高性能的并发编程基础

       在现代多核处理器系统中,原子操作是实现高效并发程序的重要工具,特别是在实现无锁数据结构、计数器、标志位等场景中。

http://www.dtcms.com/a/435331.html

相关文章:

  • 珠宝行业做网站的好处网站建设平台有哪些 谢谢平台建站
  • OpenOCD 终端使用指令大全
  • JS工具函数与代码优化实战
  • 学生信息管理系统|基于Springboot的学生信息管理系统设计与实现(源码+数据库+文档)
  • 哪些ppt网站是免费的wordpress微信验证码
  • 【P0】Spring 面试篇
  • pyqt 播放视频遮罩显示 时钟
  • Day01_刷题niuke20251002
  • 做宠物商品的网站公司网页首页图片
  • 衡水建设网站长沙房地产网站建设
  • linux进程与服务
  • wordpress订阅会员seo建站技术
  • 医疗AI平台化转型:从单点试点到体系化建设的互操作性与质量控制路径研究(下)
  • JavaScript 数组清空的三种方式
  • 网站云空间和普通空间上海传媒公司官网
  • 网站标题正确书写标准微信公众号登录不上
  • 复制标签页导致的Vue动态路由失效问题解决思路
  • 从零起步学习Redis || 第六章:Redis单线程模式的实现详解
  • 影视公司网站设计河南省建设厅厅长
  • PySide6 新(建)窗口 简单示例
  • 逍遥WEBP图片转换组件XiaoyaoWebp.dll
  • 网站建设公司+长春建设部质监局网站
  • Oracle的connect by level在MySQL中的华丽变身
  • wordpress 便签四川旅游seo整站优化站优化
  • K8s基础原理
  • 学习Java第二十八天——黑马点评26~32
  • QML学习笔记(二十三)QML的MouseArea的drag
  • 数据驱动下的GBDT实战指南:从原理拆解到业务落地的方法论
  • 欧拉-马歇罗尼常数
  • 一款基于STM32F103和树莓派的无人车