我刚刚了解到Interlocked
类,现在有一些基本问题。
据我的理解,在多线程操作数值变量时应该使用Interlocked。如果这个说法是正确的,那么进行读取或者普通使用变量怎么办?
例如:
if ((iCount % 100) == 0)
我需要在那里使用Interlocked
语句吗?
当我初始化变量时呢:
Int32 iCount = 0;
在实施前,我需要确保我理解这个。
我刚刚了解到Interlocked
类,现在有一些基本问题。
据我的理解,在多线程操作数值变量时应该使用Interlocked。如果这个说法是正确的,那么进行读取或者普通使用变量怎么办?
例如:
if ((iCount % 100) == 0)
我需要在那里使用Interlocked
语句吗?
当我初始化变量时呢:
Int32 iCount = 0;
在实施前,我需要确保我理解这个。
这里有许多因素,但主要与不稳定性和原子性有关。在您的陈述中:
首先我们需要问“什么是 iCount?”。如果它是 long / ulong 类型,则不能保证它是原子的,因此你绝对需要一些保护措施(例如通过 Interlocked)来避免获取到“损坏”的值(在更新过程中读取它的一半,给出一个它实际上从未拥有过的幻影值 - 例如,从 00000000 更改为 FFFFFFFF,你可以读取 0000FFFF 或 FFFF0000)。如果它是 int 类型,则保证是原子的。下一个问题是:我需要看到更新吗?CPU 内置了各种级别的缓存,看似从字段中读取的代码可能实际上只是从本地寄存器或缓存中读取 - 并且从未触及实际内存。如果存在风险,则可以通过使用 Interlocked 来减轻这种情况,尽管在许多情况下,使用 volatile 也可以防止这种情况。if ((iCount % 100) == 0)
Do I need to use an Interlocked statement there?
What about when I'm initializing the variable:
Int32 iCount = 0;
字段初始化器仅在一个线程上执行,因此不需要额外的保护 - 这很好。
然而!多线程编程很困难。如果您有任何疑虑,请保持简单:使用 lock
。例如(假设您想要每个实例同步):
private int iCount = 0;
private readonly object syncLock = new object();
...
lock(syncLock) {
// code that reads or manipulates iCount
}
long
,这是非常危险的。同样,原子性只是这里故事的一部分。 - Marc Gravell