使代码线程安全而不使用 lock 语句



我想从几个线程调用以下代码。

// 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)

最新更新