这几天在思考这个问题,起因为是无锁队列详细分解——Lock与Cache,到底有没有锁?,然后写的demo程序,两个线程对计数器各累加500次,只使用cas,验证最后是否为1000。
因为看链接中说的是cas由ring bus总线仲裁处理,再加上cache的MESIF协议,但是由于store buffer和invalid queue的存在,可能获取到的数据不是最新的,所以会存在问题。
后来翻阅两个star很多的开源dpdk和skynet中自旋锁实现,分别如下:
58 typedef struct {
59 volatile int locked; /**< lock status 0 = unlocked, 1 = locked */
60 } rte_spinlock_t;
89 static inline void
90 rte_spinlock_lock(rte_spinlock_t *sl)
91 {
92 while (__sync_lock_test_and_set(&sl->locked, 1))
93 while(sl->locked)
94 rte_pause();
95 }
96 #endif
11 struct spinlock {
12 int lock;
13 };
25 static inline int
26 spinlock_trylock(struct spinlock *lock) {
27 return __sync_lock_test_and_set(&lock->lock,1) == 0;
28 }
然后前者比后者多一个关键字volatile,这里的作用C/C++ Volatile关键词深度剖析。况且spinlock本身也跟cache中的MESIF有关,包括引起的问题和优化。两个开源都在相关业务中使用过,都没有出现问题,所以比较好奇看下__sync_lock_test_and_set
原理,是不是仅如文中的描述那般,但是查了下api说明__sync_lock_test_and_set,有如下"An acquire memory barrier is created when this function is invoked."说明,和5.44 Built-in functions for atomic memory access
中有如下"This builtin is not a full barrier, but rather an acquire barrier. This means that references after the builtin cannot move to (or be speculated to) before the builtin, but previous memory stores may not be globally visible yet, and previous memory loads may not yet be satisfied. "说明。
Acquire and Release Semantics和并发编程系列之一:锁的意义中有"Acquire semantics is a property which can only apply to operations which read from shared memory, whether they are read-modify-write operations or plain loads. The operation is then considered a read-acquire. Acquire semantics prevent memory reordering of the read-acquire with any read or write operation which follows it in program order. (注:Acquire语义是一个作用于内存读操作上的特性,此内存读操作即被视为read-acquire。Acquire语义禁止read-acquire之后所有的内存读写操作,被提前到read-acquire操作之前进行。")
所以也就解决了我心中的疑问。家里没有特殊上网软件,没有找到__sync_lock_test_and_set
实现源码,后期补上。
发现leveldb中有些基础代码实现挺赞的,学习下。
网友评论