Interlocked.Exchange对后续指令的影响及线程间内存可见性问询
线程可见性与Interlocked.Exchange的内存顺序问题
问题场景
假设线程1执行以下代码:
this.Field.Flag = false; ... var oldValue = Interlocked.Exchange(ref this.Field, newValue); oldValue.Flag = true;
当线程2检测到oldValue.Flag == true时,即便它未通过Interlocked或Volatile方式读取this.Field,是否可以确保该线程也能检测到this.Field == newValue?换而言之,是否可以保证Interlocked.Exchange的执行效果被其他线程可见后,其后续指令的执行效果才会对外可见?
回答
可以确保线程2检测到oldValue.Flag == true时,必然能看到this.Field == newValue,核心原因是Interlocked.Exchange会触发全内存屏障(Full Memory Barrier):
- 全内存屏障会严格限制指令重排与内存可见性顺序:屏障之前的所有内存操作必须完全完成并对其他线程可见后,屏障之后的内存操作才能执行并对外暴露。
- 对应到线程1的代码:
Interlocked.Exchange(ref this.Field, newValue)(更新Field为新值)属于屏障前的操作,oldValue.Flag = true属于屏障后的操作。这意味着,this.Field变为newValue的状态,一定会在oldValue.Flag变为true的状态被其他线程感知到之前,就已经对外可见。 - 因此当线程2读到
oldValue.Flag == true时,线程1的Field更新操作必然已经对线程2可见,哪怕线程2用普通方式读取this.Field,也能确保读到的是newValue。
内容的提问来源于stack exchange,提问作者andresp
相关产品推荐
相关产品推荐

