【发布时间】:2020-02-04 10:32:28
【问题描述】:
当我使用 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 值,从而导致超过 1,000,000 次迭代。虽然我无法在实践中产生这种情况。上面的代码总是在我的机器上打印 OK。这是否意味着代码是线程安全的?或者我应该使用lock 同步对i 变量的访问?
(* 根据我的测试,平均每 2 次迭代发生一次线程切换)
【问题讨论】:
-
你认为
i为什么会缓存在每个线程中?请参阅this SharpLab IL 以深入了解。 -
@AndreasHassing 像这样的语句引起了我的担忧:编译器、CLR 或 CPU 可能会引入缓存优化,这样对变量的赋值不会立即对其他线程可见。 Part 4: Advanced Threading
标签: c# async-await thread-safety threadpool