现代 CPU 并不总是按照更新的顺序将数据写入内存,例如,如果您运行伪代码(为简单起见,假设变量总是存储在内存中);
a = 1
b = a + 1
... CPU 很可能会b
在写入内存之前先写入a
内存。只要您在单个线程中运行,这并不是真正的问题,因为一旦进行了分配,运行上述代码的线程将永远不会看到任一变量的旧值。
多线程是另一回事,您会认为以下代码会让另一个线程获取您繁重计算的价值;
a = heavy_computation()
b = DONE
...另一个线程在做...
repeat while b != DONE
nothing
result = a
但问题是在将结果存储到内存之前可能会在内存中设置完成标志,因此其他线程可能会在计算结果写入内存之前获取内存地址 a 的值。
同样的问题 -如果Thread.start
并且Thread.join
没有“发生在之前”的保证- 会给你这样的代码问题;
a = 1
Thread.start newthread
...
newthread:
do_computation(a)
...因为a
线程启动时可能没有将值存储到内存中。
由于您几乎总是希望新线程能够使用您在启动之前初始化的数据,Thread.start
因此具有“发生在之前”的保证,即保证在调用之前已更新的数据Thread.start
可用于新线程。同样的事情也适用于新线程写入Thread.join
的数据在终止后对加入它的线程是可见的。
它只是使线程更容易。