linux 内核同步互斥技术之原子变量

原子变量用来实现对整数的互斥访问,通常用来实现计数器。
例如,我们写一行代码把变量 a 加 1,编译器把代码编译成 3 条汇编指令。
(1)把变量 a 从内存加载到寄存器。
(2)把寄存器的值加 1。
(3)把寄存器的值写回内存。
在单处理器系统中,如果进程 1 和进程 2 都执行把变量 a 加 1 的操作,可能出现下面的执行顺序:

预期结果是处理器 1 和处理器 2 执行完以后变量 a 的值加 2,但是因为在处理器 1 把变量 a 的新值写回内存之前,处理器 2 从内存读取变量 a 的旧值,导致处理器 1 和处理器 2执行完以后变量 a 的值只增加 1。
    原子变量可以解决这种问题,使 3 个操作成为一个原子操作。
    内核定义了 3 种原子变量。
(1)整数原子变量,数据类型是 atomic_t。
include/linux/types.h
typedef struct {
    int counter;
} atomic_t;

(2)长整数原子变量,数据类型是 atomic_long_t。
(3)64 位整数原子变量,数据类型是 atomic64_t。
下面以整数原子变量为例说明使用方法。初始化静态原子变量的方法如下:
atomic_t <name> = ATOMIC_INIT(n);
在运行中动态初始化原子变量的方法如下:
atomic_set(v, i);
把原子变量 v 的值初始化为 i。
常用的原子变量操作函数如下。
(1) atomic_read(v)
读取原子变量 v 的值。
(2) atomic_add_return(i, v)
把原子变量 v 的值加上 i,并且返回新值。
(3) atomic_add(i, v)
把原子变量 v 的值加上 i。
(4) atomic_inc(v)
把原子变量 v 的值加上 1。
(5) int atomic_add_unless(atomic_t *v, int a, int u);
如果原子变量 v 的值不是 u,那么把原子变量 v 的值加上 a,并且返回 1,否则返回 0。
(6) atomic_inc_not_zero(v)
如果原子变量 v 的值不是 0,那么把原子变量 v 的值加上 1,并且返回 1,否则返回 0。
(7) atomic_sub_return(i, v)
把原子变量 v 的值减去 i,并且返回新值。
(8) atomic_sub_and_test(i, v)
把原子变量 v 的值减去 i,测试新值是否为 0,如果为 0,返回真。
(9) atomic_sub(i, v)
把原子变量 v 的值减去 i。
(10) atomic_dec(v)
把原子变量 v 的值减去 1。
(11) atomic_cmpxchg(v, old, new)
执行原子比较交换, 如果原子变量 v 的值等于 old, 那么把原子变量 v 的值设置为 new。返回值总是原子变量 v 的旧值。
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一叶知秋yyds

分享是一种美德,感谢金主打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值