异步代码,共享变量,线程池线程和线程安全 [英] Asynchronous code, shared variables, thread-pool threads and thread safety
问题描述
当我使用async/await编写异步代码时,通常使用 ConfigureAwait(false)
为避免捕获上下文,我的代码正在跳转
从一个线程池线程到每个await
之后的下一个线程池线程.这引起了对线程安全性的担忧.这段代码安全吗?
When I write asynchronous code with async/await, usually with ConfigureAwait(false)
to avoid capturing the context, my code is jumping
from one thread-pool thread to the next after each await
. This raises concerns about thread safety. Is this code safe?
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次迭代.我实际上无法产生这种情况.上面的代码在我的机器上始终可以正常打印.这是否意味着代码是线程安全的?或者,我应该使用
The variable i
is unprotected, and is accessed by multiple thread-pool threads*. Although the pattern of access is non-concurrent, it should be theoretically possible for each thread to increment a locally cached value of i
, resulting to more than 1,000,000 iterations. I am unable to produce this scenario in practice though. The code above always prints OK in my machine. Does this mean that the code is thread safe? Or I should synchronize the access to the i
variable using a lock
?
(*根据我的测试,平均每2次迭代就会发生一次线程切换)
(* one thread switch occurs every 2 iterations on average, according to my tests)
推荐答案
线程安全性的问题与读取/写入内存有关.即使这可以继续在其他线程上执行,也不会在此处并发执行任何操作.
The problem with thread safety is about reading/writing memory. Even when this could continue on a different thread, nothing here is executed concurrent.
这篇关于异步代码,共享变量,线程池线程和线程安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!