0%

可见性与有序性

一、可见性

1.1、狭义内存可见性

导致“内存可见性”问题的本质原因是:在现代多CPU/CPU核处理器架构下,为提升存储性能,引入了高速缓存-写缓冲器-失效队列机制,但是该机制会使得当线程A和线程B分别在不同的CPU/CPU核上运行,A欲对主存作的修改操作并非直接作用于主存而是首先作用于本地的高速缓存,此时B所在CPU/CPU核内的高速缓存并不能感知到这个修改操作

另外,根据以上描述可知,“内存可见性”问题的产生源于“处理器架构”,故而,其他语言都存在“内存可见性”问题,比如Go,Rust等。

1.2、广义内存可见性

以上描述的内存可见性是“狭义内存可见性”,接下来叙述“广义内存可见性”:

即“操作A对操作B逻辑内存可见”,当A和B(操作A和操作B可属于同一线程,也可属于不同线程)操作同一份内存时,除了“A写B读,B读不能感知A的写”不是A对B内存可见之外,其余的(即“A写B读,B能感知A的写”,“A写B写”,“A读B读”和“A读B写”)都是A对B内存可见;当A和B操作不同内存时,则A对B内存可见恒成立

另外,关于“广义内存可见性”有以下两点说明:

  • 与“狭义内存可见性”的关系:“广义内存可见性”涵盖“狭义内存可见性”,这是显而易见的,“狭义内存可见性”描述的内存不可见,属于“操作同一份内存时,A写B读,B读不能感知A的写”情形
  • 与“重排序”的关系:重排序也是导致内存不可见的一种情形,但需要明确的是,只有“编写时,A写操作先于B读操作,A和B操作同一份内存,重排序A和B,B读不能感知A的写”这种重排序情形才会导致内存不可见(此时,属于“操作同一份内存时,A写B读,B读不能感知A的写”情形),其他的重排序情形并不会导致内存不可见

后续无特殊说明,“可见性”指的都是“广义内存可见性”。

二、有序性

2.1、狭义有序性

导致“有序性”问题的本质原因有3个:

  • 在编译器/解释器的层面,为优化程序执行速度,在遵循一定限制条件前提下,编译器编译/解释器解释得到的目标指令代码可能是经过重排序的
  • 在处理器的层面,为优化指令执行速度,在遵循一定限制条件前提下,指令最终可能重排序执行

另外,根据以上描述可知,“有序性”问题的产生源于“编译器/解释器”和“处理器架构”,既然涉及到“处理器架构”,那么其他语言显然同样会存在“有序性”问题,比如Go,Rust等。

2.2、广义有序性

以上描述的有序性是“狭义有序性”,其特点是“强调物理有序,不允许重排序”。接下来叙述“广义有序性”:

强调逻辑有序,即允许重排序,只要执行结果跟物理有序一致即可

后续无特殊说明,“有序性”指的都是“广义有序性”。

三、其他

“广义内存可见性”与“广义有序性”等价,即“存在可见性问题即存在有序性问题,存在有序性问题也即存在可见性问题”,“狭义内存可见性/狭义有序性”是“广义内存可见性/广义有序性”的子集,“狭义内存可见性”和“狭义有序性”不等价。


参考文献

[1]https://juejin.im/post/5d67e78d5188251e073a39e5

您的支持将鼓励我继续分享!