考虑以下摘自Wikipedia的示例,该示例略有改动,其中程序的步骤对应于各个处理器指令:
x = 0;
f = 0;
Thread #1:
while (f == 0);
print x;
Thread #2:
x = 42;
f = 1;
[我知道,当线程在两个不同的物理核心/处理器上运行时,由于顺序混乱,print
语句可能会打印不同的值(42或0)。
但是我不明白为什么这在单核计算机上不是问题,因为这两个线程在同一核上运行(通过抢占)。根据Wikipedia:
[当程序在单CPU机器上运行时,硬件会执行必要的簿记操作,以确保程序执行时就像所有内存操作都是按照程序员指定的顺序(程序顺序)执行的,因此不需要内存屏障。
据我所知,单核CPU也会对内存访问进行重新排序(如果它们的内存模型较弱,那么如何确保保留程序顺序?
CPU不会意识到这是两个线程。线程是一种软件构造(1)。
因此,CPU按以下顺序查看这些指令:
store x = 42
store f = 1
test f == 0
jump if true ; not taken
load x
如果CPU在加载后将x的存储重新排序到最后,它将更改结果。虽然允许CPU无序执行,但只有在不改变结果的情况下才执行此操作。如果允许这样做,实际上每个指令序列都可能会失败。不可能产生一个工作程序。
在这种情况下,不允许单个CPU在相同地址的负载之后重新排序存储。至少,到目前为止,CPU可以看到它尚未重新排序。就L1,L2,L3缓存和主内存(以及其他CPU!)而言,可能尚未提交存储。
((1)像HyperThreads这样的东西,在现代CPU中是常见的,每个内核有两个线程,因此不算作“单CPU”。你的问题。