在不使用lock语句的情况下使代码线程安全

时间:2017-05-16 10:13:33

标签: c# multithreading thread-safety locking

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

// 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语句中生效。

这可以通过lock语句包围代码来解决。

有没有办法在不使用lock语句的情况下使其线程安全?

2 个答案:

答案 0 :(得分:2)

  

这当然不是线程安全的,因为如果在运行时第一个线程在x递增之后但在评估之前停止。然后第二个线程递增,x被知道2,所以if语句为真。然后我们返回第一个线程并且它也知道为真。

事实并非如此。

Interlocked.Increment是原子操作,不需要额外的lock。 (否则应该是什么意思?)

该值正在递增,您将获得递增的值。即使之后发生了另一个增量,您仍然具有第一个增量值。所以if会评估为false。

您的代码是线程安全的。

答案 1 :(得分:0)

我认为你的假设不正确。 Interlocked.Increment的返回值是增量后的值,而不是评估时x的值。 x完全有可能被另一个线程更改,因此以下情况属实:

int x = 1;
var y = Interlocked.Increment(ref x);

if(x!=y)