我想从几个线程调用以下代码。
// x is a global/member and initialized to 0
if (Interlocked.Increment(ref x) == 2)
{
// do something only once
}
这当然不是线程安全的:如果在运行时第一个线程在x
递增之后但在评估之前停止,然后第二个线程递增x
所以现在是 2,那么 if
语句是true
。然后我们回到第一个线程,它在 if
语句中也为 true。
这可以通过在代码周围用 lock
语句来修复。
有没有办法在不使用 lock
语句的情况下使其线程安全?
这当然不是线程安全的,因为如果在运行时第一个线程在 x 递增之后但在评估之前停止。然后第二个线程递增,x 知道 2,所以 if 语句为真。然后我们回到第一个线程,它也知道是真的。
这不是真的。
Interlocked.Increment
是原子操作,不需要额外的lock
。(否则这有什么意义呢?
该值正在递增,您将获得递增的值。 即使之后发生了另一个增量,您仍然具有第一个增量值。所以 if 的计算结果为 false。
您的代码是线程安全的。
我认为你的假设是不正确的。 Interlocked.Increment
的返回值是增量后的值,而不是评估时x
的值。 x
完全有可能被另一个线程更改,因此以下内容是正确的:
int x = 1;
var y = Interlocked.Increment(ref x);
if(x!=y)