原子位操作

Linux kernel提供了一些原子位操作的API,比如通过set_bit(int nr, void *addr)设置addr上的第nr位,而clear_bit(int nr, void *addr)用来清除addr上的第nr位。

关于使用原子位操作和非原子位操作的区别,《Linux内核设计与实现》一书中,描述的不是很清楚,很容易引起歧义:
“For example, assume you issue two atomic bit operations: Initially set the bit and then clear the bit. Without atomic operations, the bit might end up cleared, but it might never have been set.”

其实可以这样理解,与对变量进行加加、减减等操作类似,置位操作对应到C语言虽然只有一条语句,但实际上是由多条汇编指令完成的:

  • 读取变量的值到寄存器中
  • 对寄存器中的值进行置位操作
  • 将寄存器中的值写回变量

考虑这样一种场景,全局变量i的初始值为0,CPU0上的执行线程对其第0位置位,同时CPU1上的执行线程正对其第1位置位:

CPU0CPU1
LOAD i (0)
SETBIT i,0x1 (0x1)LOAD i (0)
STORE i (0x1)SETBIT i,0x2 (0x2)
STORE i (0x2)

所以当多个执行线程同一时刻对同一变量进行位操作时,就会发生竞争条件。回到上述例子,本来预期的结果是i=0x3, 但当使用非原子位操作时,就有可能得到错误的结果,即i的值是0x1或者0x2。而原子位操作就可以确保结果的正确性,即i=0x3。

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():该函数用于原子地将一个值与一个变量进行按位异或操作,并返回之前的值。 这些原子操作函数可以保证在多线程环境下对共享资源的操作是原子的,避免了竞争条件和数据不一致的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值