5

例子:

Thread a:  Interlocked.Increment(ref x);

Thread b:  int currentValue = x;

假设线程 b 在线程 a 之后执行,线程 b 中的“currentValue”是否保证为增量值?或者,线程 b 是否需要执行 Thread.VolatileRead(ref x)?

4

2 回答 2

5

从技术上讲,这取决于运行 .NET 的 CPU,但对于任何常见的 CPU,答案都是肯定的,Interlocked.Increment 保证缓存一致性。它充当MESI 要求的内存屏障。

CPU 可以在其缓存中包含无效的行,但它还不知道该行是无效的 - 无效队列包含尚未被执行的无效。(失效队列位于缓存的另一“边”;CPU 无法扫描它,因为它可以扫描存储缓冲区)。因此,需要内存屏障。

http://en.wikipedia.org/wiki/MESI_protocol (x86)

MOESI(用于 AMD64 芯片)非常相似:

http://en.wikipedia.org/wiki/MOESI_protocol (AMD64)

于 2012-12-12T23:39:46.427 回答
3

据我了解,只有在其他 Interlocked 方法访问时才能保证 Interlocked。在 x86 系统上谈论 64 位值时,这可能尤其重要,因为它不能保证是原子的,因此撕裂值是一个问题。稳健地读取可由 Interlocked 更改的值的一个好技巧是 CompareExchange:

int val = Interlocked.CompareExchange(ref field, 0, 0);

这会将 的值field变为 0,但前提是旧值为 0 - 否则它什么也不做。无论哪种方式,都会返回旧值。所以基本上:它读取值而不更改它,并且与其他互锁方法相比是安全的。

于 2012-12-12T23:54:46.513 回答