异步代码,共享变量,线程池线程和线程安全

The*_*ias 8 c# thread-safety threadpool async-await

当我使用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");
}
Run Code Online (Sandbox Code Playgroud)

该变量i不受保护,可以由多个线程池线程访问*。尽管访问模式是非并行的,但是从理论上讲,每个线程都应该可以将的本地缓存值递增i,从而导致超过1,000,000次迭代。我实际上无法产生这种情况。上面的代码在我的机器上始终可以正常打印。这是否意味着代码是线程安全的?或者我应该i使用lock?同步对变量的访问?

(*根据我的测试,平均每2次迭代发生一次线程切换)

Jer*_*gen 2

线程安全的问题在于读/写内存。即使这可以在不同的线程上继续,这里也不会并发执行任何内容。

  • @TheodorZoulias 线程 A 运行,递增“i”。代码点击“await”,线程 A 将所有状态传递给线程 B 并返回到池中。线程 B 递增“i”。点击“等待”。然后,线程 B 将所有状态传递给线程 C,它返回到池等。在任何时候都不会并发访问“i”,不需要线程安全,发生线程切换并不重要,所有需要的状态都被传递到运行延续的新线程中。没有共享状态,这就是您不需要同步的原因。 (2认同)