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");
}
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
?
(* one thread switch occurs every 2 iterations on average, according to my tests)