它是等待锁定,还是乐观地尝试并在存在争用时重试(如 TVar)。
atomicModifyIORef 在您所在的底层硬件架构上使用锁定指令,以原子方式交换指向已分配 Haskell 对象的指针。
在 x86 上,它使用 cas 指令,作为原始语言暴露给 via atomicModifyMutVar#
,它在 Cmm 中作为运行时服务实现为:
stg_atomicModifyMutVarzh
{
...
retry:
x = StgMutVar_var(mv);
StgThunk_payload(z,1) = x;
#ifdef THREADED_RTS
(h) = foreign "C" cas(mv + SIZEOF_StgHeader + OFFSET_StgMutVar_var, x, y) [];
if (h != x) { goto retry; }
#else
StgMutVar_var(mv) = y;
#endif
...
}
也就是说,它将尝试进行交换,否则重试。
cas 作为原语的实现展示了我们如何深入到金属:
/*
* Compare-and-swap. Atomically does this:
*/
EXTERN_INLINE StgWord cas(StgVolatilePtr p, StgWord o, StgWord n);
/*
* CMPXCHG - the single-word atomic compare-and-exchange instruction. Used
* in the STM implementation.
*/
EXTERN_INLINE StgWord
cas(StgVolatilePtr p, StgWord o, StgWord n)
{
#if i386_HOST_ARCH || x86_64_HOST_ARCH
__asm__ __volatile__ (
"lock\ncmpxchg %3,%1"
:"=a"(o), "=m" (*(volatile unsigned int *)p)
:"0" (o), "r" (n));
return o;
#elif arm_HOST_ARCH && defined(arm_HOST_ARCH_PRE_ARMv6)
StgWord r;
arm_atomic_spin_lock();
r = *p;
if (r == o) { *p = n; }
arm_atomic_spin_unlock();
return r;
#elif !defined(WITHSMP)
StgWord result;
result = *p;
if (result == o) {
*p = n;
}
return result;
所以你可以看到它能够在 Intel 中使用原子指令,在其他架构上将使用不同的机制。运行时将重试。