C语言的原子操作

一、什么是原子操作

原子操作是不可分割的,在执行完毕之前不会被任何其它任务或事件中断,可以视为最小的操作单元,是在执行的过程中、不会导致对数据的并发访问的、最小操作,因此称为原子操作。最简单的原子操作,就是交换一个寄存器和一个内存地址的值,

原子操作,是实现锁机制的基础。mutex,spinlock等,在其底层都有一个关键的原子操作。在编程语言中一般分为两种情况:

  1. 在单线程中, 能够在单条指令中完成的操作都可以认为是" 原子操作",因为中断只能发生于指令之间
  2. 在多线程中,不能被其它进程(线程)打断的操作就叫原子操作

二、为什么需要原子操作

在多核处理器的机器上,对于同一个变量值所存在的内存区域可能被多个CPU短时间内同时访问,从而导致该值得不稳定性。例如在多线程中,初始化 i = 0,对于 i++ 这个操作,同时有2个线程对其进行了调用则有可能导致第一个线程用时 i 的值为 2

i++ 的操作分为三步:

  1. 内存访问,读取i变量的值到CPU的寄存器中;
  2. 使寄存器中的值 +1;
  3. 将寄存器中的值写回到内存。

由此可见,i++并不是原子操作,在没有线程保护的多线程处理器中,每一步都有可能被外部中断给打断,从而影响到 i 的值。如果2个线程同时调用了 i++,i 可能直接从 0 变为 2——线程1 在寄存器中使得 i自增1的同时线程2也在做此操作,因此当取出寄存器中i的值到内存时,i 不知不觉被加了2次

三、原子操作分类

3.1 硬件级原子操作

如果是单处理器系统,任何操作只要在单条指令中完成,都可以认为是原子操作

如果是多处理器,任意单条指令操作都会有可能受到干扰。x86 平台CPU提供了在指令执行期间对总线加锁的手段保证原子性

3.2 软件级原子操作

软件级原子操作实现依赖于硬件原子操作的支持,例如在linux环境下,内核提供了两组原子操作接口:

  1. 针对整数进行操作
  2. 针对位进行操作

四、原子操作API


// 将value加到*ptr上,结果更新到*ptr,并返回操作之前*ptr的值
type __sync_fetch_and_add (type *ptr, type value, ...) 

// 从*ptr减去value,结果更新到*ptr,并返回操作之前*ptr的值
type __sync_fetch_and_sub (type *ptr, type value, ...) 

// 将*ptr与value相或,结果更新到*ptr, 并返回操作之前*ptr的值
type __sync_fetch_and_or (type *ptr, type value, ...) 

// 将*ptr与value相与,结果更新到*ptr,并返回操作之前*ptr的值
type __sync_fetch_and_and (type *ptr, type value, ...) 

// 将*ptr与value异或,结果更新到*ptr,并返回操作之前*ptr的值
type __sync_fetch_and_xor (type *ptr, type value, ...) 

// 将*ptr取反后,与value相与,结果更新到*ptr,并返回操作之前*ptr的值
type __sync_fetch_and_nand (type *ptr, type value, ...) 

// 将value加到*ptr上,结果更新到*ptr,并返回操作之后新*ptr的值
type __sync_add_and_fetch (type *ptr, type value, ...) 

// 从*ptr减去value,结果更新到*ptr,并返回操作之后新*ptr的值
type __sync_sub_and_fetch (type *ptr, type value, ...) 

// 将*ptr与value相或, 结果更新到*ptr,并返回操作之后新*ptr的值
type __sync_or_and_fetch (type *ptr, type value, ...) 

// 将*ptr与value相与,结果更新到*ptr,并返回操作之后新*ptr的值
type __sync_and_and_fetch (type *ptr, type value, ...) 

// 将*ptr与value异或,结果更新到*ptr,并返回操作之后新*ptr的值
type __sync_xor_and_fetch (type *ptr, type value, ...) 

// 将*ptr取反后,与value相与,结果更新到*ptr,并返回操作之后新*ptr的值
type __sync_nand_and_fetch (type *ptr, type value, ...) 

// 比较*ptr与oldval的值,如果两者相等,则将newval更新到*ptr并返回true
bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...) 

// 比较*ptr与oldval的值,如果两者相等,则将newval更新到*ptr并返回操作之前*ptr的值
type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...) 
  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
C语言原子操作函数是一种特殊的函数,用于在多线程环境下对共享资源进行原子操作,即不会被其他线程中断的操作。这些函数可以确保在执行期间不会发生竞争条件或数据不一致的情况。 C语言中常用的原子操作函数有以下几种: 1. atomic_flag_test_and_set():该函数用于设置一个原子标志,并返回之前的值。如果之前的值为true,则表示已经被设置过,否则表示之前未被设置。 2. atomic_flag_clear():该函数用于清除一个原子标志,将其设置为false。 3. atomic_load():该函数用于原子地加载一个变量的值,并返回该值。 4. atomic_store():该函数用于原子地存储一个值到一个变量中。 5. atomic_exchange():该函数用于原子地交换两个变量的值。 6. atomic_compare_exchange_strong():该函数用于原子地比较并交换两个变量的值。如果比较成功,则交换并返回true;否则返回false。 7. atomic_fetch_add():该函数用于原子地将一个值加到一个变量中,并返回之前的值。 8. atomic_fetch_sub():该函数用于原子地将一个值从一个变量中减去,并返回之前的值。 9. atomic_fetch_and():该函数用于原子地将一个值与一个变量进行按位与操作,并返回之前的值。 10. atomic_fetch_or():该函数用于原子地将一个值与一个变量进行按位或操作,并返回之前的值。 11. atomic_fetch_xor():该函数用于原子地将一个值与一个变量进行按位异或操作,并返回之前的值。 这些原子操作函数可以保证在多线程环境下对共享资源的操作原子的,避免了竞争条件和数据不一致的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值