lock{}
是Monitor
类的语法糖。(哦,是语法糖)我正在尝试解决一些简单的多线程问题,发现无法完全理解如何通过锁定某个随意的内存单元来保护其他整个内存不会被缓存到寄存器/CPU缓存等中。使用代码示例更容易解释我所说的内容:
for (int i = 0; i < 100 * 1000 * 1000; ++i) {
ms_Sum += 1;
}
最终ms_Sum
将包含100000000
,这当然是期望的。
现在我们将在2个不同的线程上执行相同的循环,并将上限减半。
for (int i = 0; i < 50 * 1000 * 1000; ++i) {
ms_Sum += 1;
}
由于缺乏同步,我们得到了不正确的结果——在我的4核机器上,它是一个接近于 52 388 219
的随机数,稍微大于 100 000 000
的一半。如果我们将 ms_Sum += 1;
放入 lock{}
中,那么我们肯定会得到完全正确的结果 100 000 000
。但对我来说,有趣的是(实话实说,我曾经期望过这样的行为),在 ms_Sum += 1;
行之前或之后添加 lock
几乎可以使答案正确:
for (int i = 0; i < 50 * 1000 * 1000; ++i) {
lock (ms_Lock) {}; // Note curly brackets
ms_Sum += 1;
}
在这种情况下,我通常会得到ms_Sum = 99 999 920
,非常接近。
问题:为什么lock(ms_Lock) { ms_Counter += 1; }
可以使程序完全正确,而lock(ms_Lock) {}; ms_Counter += 1;
只能让程序几乎正确?锁定任意的ms_Lock
变量如何使整个内存稳定?
非常感谢!
P.S. 我去读关于多线程的书了。
类似的问题