【发布时间】:2011-08-20 13:20:56
【问题描述】:
首先,我知道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 变量如何使整个内存稳定?
非常感谢!
附言去阅读有关多线程的书籍。
类似问题
How does the lock statement ensure intra processor synchronization?
Thread synchronization. Why exactly this lock isn't enough to synchronize threads
【问题讨论】:
-
你的意思是“句法”糖。 :)
-
@Hugh:有一些合成的东西。
-
没有人解释残差。它是由 Windows 线程调度程序引起的。使用 start.exe /affinity 1 运行无锁定版本以获得可比较的结果。
标签: c# multithreading locking memory-barriers