从该博客开始,会有一些小系列预计有4-5篇博文来介绍,锁的应用和实践,我们常常听到spin lock,wait-free,lock-free,这到底是怎么回事,我们能不能自己实现一个spin lock,原理是什么?这个小系列就讨论这个内容。
首先我们来看两个基本操作compare_and_swap和fetch_and_add,基本上lock-free的操作都会依赖这两个基本的原子操作。特别是compare_and_swap这个原子操作,它源于IBM System 370,其包含三个参数:(1)共享内存的地址(*p),(2)该地址期望的值(old_value),(3)一个新值(new_value)。只有当*p == old_value时,才产生交换操作,返回真值,否则返回假值,相当于如下代码 :template<class T>
bool CAS(T* addr, T exp, T val) //只有在整个函数过程具有原子性时才正确,实际的代码参照下面的汇编代码。
{
if(*addr == exp){
*addr = val;
return true;
}
return false;
}
在下面的代码中我们会看到compare_and_swap使用了lock指令,用于锁总线,setz会判断cmpxchg指令后ZF符号位是否置位,可以知道是否发生了一次交换。以下是一段可以执行的代码,void* sum(void*)函数通过不同的编译命令生成不同的代码,其结果都是用10个线程对一个全局变量进行加和的简单操作。但分别采用了pthread提供的mutex,fetch_and_add方法,完全无锁的方法,应用cas的三种方式,其中sum_with_cas_imp_yield就基本是spinlock的实现了。
下一篇我来公布在我的测试机的实验结果,并且继续探讨其他lock-free的话题。
#include <pthread.h>
#include <stdio.h>
#include <string.h>#incl