蓝盟IT外包,让我们谈谈原子操作

发布者:上海IT外包来源:http://www.lanmon.net点击数:2070

蓝盟IT小贴士,来喽!
小粒度——指令
根据英特尔手册卷3第8章的说明,x86使用三种机制来实现原子操作。
1. Guaranteed  atomic  operations。 保障原子操作是保证原子性的基本读/写存储器操作。 通常,读写位于一个cache  line上的数据是原子的。
2 .使用2. bus  lock、LOCK#信号和命令的lock前缀。 锁定总线的方式很简单,进行原子操作的cpu在bus上assert  lock  #信号,这时其他cpu的操作住在block。
3. cache  lock是使用cache性能协议(MESI协议)来实现的。 如果要访问的内存空间已经位于当前cpu的cache上,请使用cache一致性协议来实现原子操作。 否则,锁定公共汽车。
英特尔的初始cpu  (例如英特尔386、英特尔486和奔腾处理器)通过bus  lock实现原子操作。 这样实现的问题是,在完全不相关的两个cpu之间,总线锁也会竞争,整体性能会下降。 在随后的cpu中,intel优化了这个问题。 如果进行原子操作的内存已经引入cache,cpu将使用cache完整性协议保证原子性。 这叫做cache  lock。 与bus  lock相比,cache  lock的粒度更细,可以得到更好的性能。
在x86中,有些指令具有lock语义,例如更新XCHG和段描述符。 其他命令可以手动添加lock前缀以实现lock语义,如BTS、BTR和CMPXCHG命令。 在这些命令中,最核心的是CAS(Compare  And  Swap  )命令,是实现各种锁定语义的核心命令。 与具有原子意义的XCHG不同,CAS操作是以“lock  CMPXCHG”的形式实现的。 通常,原子操作的数据长度不超过8字节,也不允许同时对两个存储器地址进行CAS操作(如果可能的话,无锁双向链表不是梦)。
原子操作的另一个话题是ABA问题,水平有限,所以谈不下去。 简单举个例子,在linux内核的slub实现中,不是同时CAS两个存储器地址的黑魔术,而是用CMPXCHG16B命令解决ABA问题的宏函数,感兴趣的可以深入。粒度大
如果原子操作的对象尺寸在16字节或8字节以内,则可以用1、2命令进行原子操作。 但是,在对象的大小较大的情况下,为了实现原子操作需要锁定和COW等其他方法。 深入研究这两种方法,本质上可以看出问题已转换成16字节的原子操作。
锁上。
上锁这种方式被很好地理解,上锁的话整个临界域的操作可以看作原子操作。
内核备有各种锁、自旋锁、读写锁、seq锁、mutex、semaphore等,这些锁根据领导的倾向而不同,取决于是否允许睡眠。
简单来说,自旋锁和读写锁的核心是利用原子指令CAS操作32位/64位的值,它们都不允许休眠,但读写锁对读者进行了优化,允许多个读者同时读取数据mutex和semaphore也是基于自旋锁实现的,但可以休眠互斥区域的操作。
上锁这种方式可以看出,最核心的是命令的原子操作。
COW
对大对象原子操作的另一种方法是COW(copy  on  write  )。
cow的思想其实很简单,首先我们有这个大对象的指南。 如果需要原子上修改这个大对象的数据,因为无法进行inplace修改,所以复制这个对象的数据,用对象的副本进行修改,最后原子上修改这个对象的指针。 可以看出这里最核心的是利用命令实现指针的更换。

文/上海蓝盟  IT外包专家

IT外包
>
400-635-8089
立即
咨询
电话咨询
服务热线
400-635-8089
微信咨询
微信咨询
微信咨询
公众号
公众号
公众号
返回顶部