它的实现依赖于底层的CPU架构。对于某些CPU来讲,这很简单,例如x86能够经过
LOCK前缀直接支持Interlocked操做(有一个额外的特性就是XCHG指令老是隐式包含了LOCK前缀)。IA64和x64也直接支持原子的load-modify-store操做。
其它的多数CPU架构把这个操做分红两部分,被称为
Load-link/store-conditional。第一部分(load-link)从指定内存地址读取一个值,而且处理器会监视这个内存地址,看是否有其它处理器修改该值。第二部分(store-conditional)是若是这期间没有其它处理器修改该值,则将新值存回该地址。所以,一个原子的load-link/store-conditional操做就是经过load-link读取值,进行一些计算,而后试图store-conditional。若是store-conditional失败,那么从新开始整个操做。
1 LONG InterlockedIncrement( LONG volatile *value )
2 {
3 LONG lOriginal, lNewValue;
4 do
5 {
6 //
7 //经过load-link读取当前值
8 //能够知道写回以前是否有人修改它
9 //
10 lOriginal = load_link(value);
11
12 //
13 //计算新的值
14 //
15 lNewValue = lOriginal + 1;
16
17 //
18 //有条件的写回新值
19 //若是有人在计算期间覆写该值,则函数返回失败
20 //
21 } while ( !store_conditional(value, lNewValue));
22 return lNewValue;
23 }
请求CPU监视一个内存地址依赖于CPU本身的实现。但要记住一件事情,CPU在同一时间只能监视一个内存地址,而且这个时间是很短暂的。若是你的代码被抢占了或者在load-link后有一个硬件中断到来,那么你的store-conditional将会失败,由于CPU由于硬件中断而分心了,彻底忘记了你要求它监视的内存地址(即便CPU成功的记住了它,也不会记过久,由于硬件中断几乎都会执行本身的load-link指令,所以会替换成它本身要求监视的内存地址)。
另外,CPU可能会有点懒,在监视时并不监视内存地址,而是监视cache line,若是有人修改了一个不一样的内存位置,可是恰好跟要被监视的内存地址在同一个cache line里,store-conditional操做也会失败,即便它事实上能够成功完成。ARM架构的CPU是太懒了,以致于任何向同一块2048字节写入的操做都会致使store-conditional失败。
这对于须要用汇编语言来实现Interlocked操做的你来讲意味着什么?你须要尽量减小load-link和store-conditional之间的指令数。例如,InterlockedIncrement只不过是给值加1。你在load-link和store-conditional之间插入的指令越多,store-conditional失败的可能就越大,你就不得不重来一次。若是你在二者之间插入的指令太多了就会致使store-conditional永远不会成功。举一个极端的例子,若是你计算新值的代码须要耗时5秒,在这5秒内确定会接收到不少硬件中断,store-conditional操做就永远都会失败。