在他的新书41.2.1 Memory Location
部分,B.Stroustrup撰写以下内容:
考虑两个全局变量 b 和 c :
// thread1 char c = 0; void f() { c = 1; int x = c; } // thread2 char b = 0; void g() { b = 1; int y = b; }
现在,x == 1和y == 1,正如任何人所期望的那样。为什么这甚至值得说?考虑如果分配链接器可能会发生什么 内存中同一个字中的 c 和 b (与大多数现代硬件一样),机器无法加载或存储小于a的任何内容 字:
如果没有定义明确且合理的内存模型,线程1可能会 阅读包含 b 和 c 的字词,更改 c ,然后编写 回到记忆中的话。同时线程2可以做同样的事情 b 。然后,无论哪个线程设法首先读取该单词 wichever线程设法将其结果写回到内存中 会决定结果。我们可能 10 , 01 或 11 (但不是 00 )。记忆模型使我们免于混乱;我们得到 的 11 即可。 00 不能发生的原因是 b 和 c 的初始化(由编译器或链接器完成)之前 要么线程开始。
假设短语:
我们可能 10 , 01 或 11 (但不是 00 )
分别指变量 x 和 y 的最终值,我们怎么能得到 10 和 01 没有合理的记忆模型。我只是看不出这是怎么可能的。
我也无法理解作者在写上述最后一句话时的意思:
00 不能发生的原因是初始化 在任一线程启动之前(由编译器或链接器完成) b 和 c 。
答案 0 :(得分:5)
在没有合理内存模型的情况下可以获得01或10的原因是因为线程操作同时发生并且内存的读写不是原子的。它们需要两个步骤 - 步骤1:读取,步骤2:写入。如果没有合理的记忆模型,可能会出现以下情况:
线程1:读取00内存:00
线程2:读取00内存:00
线程1:写入10个内存:10
线程2:写入01记忆:01
结果:01
多线程编程时,多线程访问同一资源的问题很常见。例如,需要访问相同静态成员变量的多个线程。我们防止线程跨越彼此的方式是使用互斥锁和关键部分。但是,在提供的情况下,我们不需要这样做,因为内存模型为我们处理它(是明智的)。
00不可能的原因:在任一线程启动之前,内存初始化为00,因此两个线程都没有跟踪其他线程的操作,并将内存设置为00.