我想从几个线程中调用以下代码。
// 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
语句的情况下使其线程安全?
答案 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)