Quando escrevo código assíncrono com async / waitit, geralmente com ConfigureAwait(false)
para evitar capturar o contexto, meu código está saltando de um segmento de pool de threads para o próximo após cada um await
. Isso levanta preocupações sobre a segurança do encadeamento. Esse código é seguro?
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");
}
A variável não i
está protegida e é acessada por vários threads * do conjunto de encadeamentos. Embora o padrão de acesso seja não simultâneo, teoricamente deve ser possível para cada encadeamento incrementar um valor armazenado em cache localmente i
, resultando em mais de 1.000.000 de iterações. Eu sou incapaz de produzir esse cenário na prática. O código acima sempre imprime OK na minha máquina. Isso significa que o código é seguro para threads? Ou devo sincronizar o acesso à i
variável usando um lock
?
(* uma opção de thread ocorre a cada 2 iterações, em média, de acordo com meus testes)
i
é armazenado em cache em cada thread? Veja este SharpLab IL para aprofundar.