原子计数操作 — _syn_fetch_and_add等12个操作

原子计数操作  — _syn_fetch_and_add等12个操作

 

 

 

 

多线程计数操作,共享状态或者统计相关时间次数,这些都需要在多线程之间共享变量和修改变量,如此就需要在多线

程间对该变量进行互斥操作和访问.我们谭老先生早都说过了! ++i 和 i++都是不是原子性的,本质上为三步:

1. 从缓存取到寄存器

2. 在寄存器中加1

3. 再存入缓存

但是有时候由于时序的元素,多线程操作同一个全局变量,就会出现很多问题,这就是多线程并发编程的难点,尤其随

着计算器硬件技术的快速发展,多CPU多核技术更是彰显出这种困难.

其实最有效的方法就是加互斥量,后来在我们的C++11当中,提供了_syn_fetch_and_add一系列命令进行原子性操作,

随后就在网上查阅相关资料,今天将他们积累下来:

_sync_fetch_and_add系列一共有12个函数,分别:加/减/与/或异或等原子性操作函数,_syn_fetch_and_add,顾明

思义,先fetch,返回自加前的值,举例说明,count = 4,调用_sync_fetch_and_add(&count,1)之后,返回值是4,但

是count变成5. 同样的 __sync_add_and_fetch,先自加,然后返回自加后的值,这样对应的关系,与i++和++i的关系

是一样的.   12个函数如下所示:


type __sync_fetch_and_add (type *ptr, type value, ...)
type __sync_fetch_and_sub (type *ptr, type value, ...)
type __sync_fetch_and_or (type *ptr, type value, ...)
type __sync_fetch_and_and (type *ptr, type value, ...)
type __sync_fetch_and_xor (type *ptr, type value, ...)
type __sync_fetch_and_nand (type *ptr, type value, ...)

type __sync_add_and_fetch (type *ptr, type value, ...)
type __sync_sub_and_fetch (type *ptr, type value, ...)
type __sync_or_and_fetch (type *ptr, type value, ...)
type __sync_and_and_fetch (type *ptr, type value, ...)
type __sync_xor_and_fetch (type *ptr, type value, ...)
type __sync_nand_and_fetch (type *ptr, type value, ...)

上述12个函数即为所有,通过函数名字就可以知道函数的作用,需要注意的是,这个type不能乱用(type 只能是int ,

long ,long long以及对应的unsigned的类型) . 这里还有类似的原子操作:

bool __sync_bool_compare_and_swap(type *ptr, type oldval, type newval, ...)
type __sync_val_compare_and_swap(type *ptr, type oldval, type newval, ...)

这两个函数提供院子的交换和比较,如果 *ptr == oldval,就将newval写入 *ptr,第一个函数在相等并写入的情况下返

回true,第二个函数在返回操作之前的值.

有了这些装逼利器,对于多线程对全局变量进行操作(自加,自减)问题,我们就不用考虑线程锁,可以考虑使用上述

函数代替和使用pthread_mutex保护的作用是一样的,线程安全且性能完爆线程锁.  那么性能好在哪里呢 ?

下面简单介绍一下 __syn_fetch_and_add反汇编出来的指令:

804889d:f0 83 05 50 a0 04 08 lock addl $0x1,0x804a050

可以看到,add前面有一个Lock,这行汇编指令前面是f0开头,f0叫做指令前缀,Richard Blum,lock前缀的意思是对内存区

域的排他性访问.、

其实,lock是锁FSB,前端串行总行,Front Serial Bus,这个FSB是处理器和RAM直接的总线,锁住FSB,就能阻止其他处

理器或core从RAM获取数据,当然这种操作开销相当大,只能操作小的内存才可以这有做. 如果操作一大片内存,锁内存

,那么代价太大了,所以前面介绍__sync_fetch_and_add等函数,type只能是int long longlong以及对应的unsigned类型.

 

今后写项目切记,加加减减出现竞态现象的时候,一定要记起来使用这个函数!  看网上做实验比mutex性能好.

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值