现代的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
没有“happens before”保证,同样的问题也会出现在如下代码中:
a = 1
Thread.start newthread
...
newthread:
do_computation(a)
由于线程启动时可能未将值存储到内存中,因此需要注意。
由于您几乎总是希望新线程能够使用在启动前初始化的数据,因此 Thread.start
具有“happens before”保证, 也就是说,在调用Thread.start
之前更新的数据保证对新线程可用。同样,Thread.join
也是如此,其中新线程写入的数据保证在终止后对加入它的线程可见。
这使得线程处理更加容易。