Windows Programming/Interlocked变量访问

Interlocked变量访问是Windows API提供的一种对DWORD或指针类型的变量原子访问机制。[1]

对于32位地址对齐的变量,在32位CPU上的读写操作是原子的,即变量不会只被修改一部分。但访问不能保证同步。如果两个线程同时读写一个变量,不能保证是否有一个线程读操作在另一个线程的写操作之前。如果是加一操作,两个线程的执行结果可能是该变量只被加了1而不是被加了2。上述情况对64位CPU上的64位对齐变量也适用。64位系统的对应API函数,使用“64”后缀。

底层实现编辑

x86平台使用LOCK prefix指令。ia64与x64直接支持load-modify-store操作。

其它平台使用Load-link/store-conditional,先通过load-link读值,执行期望的计算,在试图通过store-conditional保存值。如果store-conditional失败,重启这些操作。实际上CPU会监视整条cache line。硬件中断会导致store-conditional失败。[2]

函数列表编辑

原子加减1操作编辑

InterlockedIncrement与InterlockedDecrement

提供了加1或者减1原子操作。 执行原子加1操作,参数Addend的值会被加1,返回值为原始操作加1后的当前值。

比较并交换操作(Compare and Swap, CAS)编辑

InterlockedCompareExchange, InterlockedCompare64Exchange128与InterlockedCompareExchangePointer函数读出其原值,原值与比较值如果相等则赋予新值的原子操作。

InterlockedCompareExchange()带有全局的内存栅障,不带全局内存栅障的对应操作为InterlockedCompareExchangeAcquire()与InterlockedCompareExchangeRelease()


原子写操作编辑

InterlockedExchange与InterlockedExchangePointer函数提供了对long与指针变量读出其原值,赋予新值的原子操作。InterlockedExchangeAdd与InterlockedExchangeSubtract函数提供了对long型变量读出其原值,加上/减少一个增量值的原子操作。

原子加法、或运算、异或运算编辑

InterlockedAnd, InterlockedOr与InterlockedXor提供了与、或、异或的原子操作

InterlockedAdd返回了变量被原子增加一个值的结果。

原子比特位测试设置编辑

InterlockedBitTestAndSet,InterlockedBitTestAndReset与InterlockedBitTestAndComplement函数提供读出变量指定比特位的原值,并置位/复位/翻转该比特位的值的原子操作。

参考文献编辑

  1. Raymond Chen: Interlocked operations don’t solve everything in “old newthing”
  2. Raymond Chen: How does InterlockedIncrement work internally? in “old newthing”