为什么Dekker在x86/x64架构的CPU上会失效!
Dekker算法是很多老教科书(含国内新教科书)上提到的一种多线程lock-free编程的算法.
这里来解释一下,为什么Dekker在x86/x64架构的CPU上是错误的.
首先看一下什么是Dekker算法:
int x=0;
int y=0;
ThreadA: ThreadB:
x=1; y=1;
r1=y; r2=x;
在CPU保证读写顺序的假设下, 当两个线程并行运行于多核CPU时,
无论读写是否交错, 必然至多有一个线程会读到0.
读到0的线程可以访问临界区,读到1的不可以.
这样就实现了一个简单的lock-free算法.
但是,遗憾的是,在不保证读写指令顺序执行的CPU上,这个算法是错误的.
CPU对读写指令进行重排的特性使得,后面的读操作可以在写操作之前完成.
也就是说,下面这个执行顺序:
r1=y;
x=1;
也是可能发生的.
只要是读写不是同一个内存地址,比如上面的例子中,
读y写x.
这样的指令就有可能乱序执行.
这种访存顺序的松弛性,是由于,CPU发出的访存指令实际还要经过一个队列,在队列中,为了优化性能,
(读读写写比读写读写快)而调整了顺序导致的.
当然,可以强制禁止CPU的这种指令重排.
x=1;
_asm mfence;
r1=y;
像上面这样写,即可强制CPU以"_asm mfence;"为界限,进行内存操作.
从而避免例子中读写乱序的发生.
:)