当我使用async/await编写异步代码时,通常会使用ConfigureAwait(false)
避免捕获上下文,每次await
后我的代码会从一个线程池线程跳到下一个线程。这引起了关于线程安全的担忧。这段代码是否安全?
static async Task Main()
{
int count = 0;
for (int i = 0; i < 1_000_000; i++)
{
Interlocked.Increment(ref count);
await Task.Yield();
}
Console.WriteLine(count == 1_000_000 ? "OK" : "Error");
}
变量i未受保护,并由多个线程池线程访问。尽管访问模式是非并发的,但理论上每个线程都可以增加本地缓存值i的值,导致超过100万次迭代。然而,在我的机器上无法实现这种情况。上面的代码总是打印“OK”。这是否意味着代码是线程安全的?还是我应该使用
lock
同步对i变量的访问?(*根据我的测试,平均每2次迭代发生一次线程切换)
i
?请参考此SharpLab IL进行深入探究。 - AndreasHassing