Когда я пишу асинхронный код с помощью 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 итераций. Я не могу представить этот сценарий на практике, хотя. Код выше всегда печатает ОК на моей машине. Означает ли это, что код является потокобезопасным? Или я должен синхронизировать доступ к переменной i
, используя lock
?
(* один поток переключается в среднем каждые 2 итерации, согласно моим тестам)