还有一个关于线程安全和 async/await 的问题。我不明白为什么我的第二个增量不是线程安全的。
class Program
{
static int totalCountB = 0;
static int totalCountA = 0;
static async Task AnotherTask()
{
totalCountA++; // Thread safe
await Task.Delay(1);
totalCountB++; // not thread safe
}
static async Task SpawnManyTasks(int taskCount)
{
await Task.WhenAll(Enumerable.Range(0, taskCount)
.Select(_ => AnotherTask()));
}
static async Task Main()
{
await SpawnManyTasks(10_000);
Console.WriteLine($"{nameof(totalCountA)} : " + totalCountA); // Output 10000
Console.WriteLine($"{nameof(totalCountB)} : " + totalCountB); // Output 9856
}
}
Run Code Online (Sandbox Code Playgroud)
我的理解是:
totalCountA++是线程安全的,因为在那之前,代码是完全同步的。await可能会在线程池上运行,但我没想到恢复的代码await将完全是多线程的。根据一些答案/博客,async/await 不应创建新线程:
我真的在这里错过了一些大事。
TotalCountA++ 是线程安全的,因为在那之前,代码是完全同步的。
是的。这是因为async方法开始在调用线程上执行,就像同步方法一样(归因:我)。
我知道await可能会在线程池上运行,但我没想到恢复await的代码将完全是多线程的。
它await不会“运行”到任何地方。这就是您链接到的我的《没有线索》文章的要点。
现在,在之后await,其余代码需要在某个地方运行。await默认情况下将捕获“上下文”并使用它来执行方法的其余部分async(归属:我)。该“上下文”是SynchronizationContext.Current,除非它是null,在这种情况下它是TaskScheduler.Current。在控制台应用程序中,这意味着上下文是线程池上下文,因此任何可用的线程池线程都将执行该方法的其余部分async。
| 归档时间: |
|
| 查看次数: |
1145 次 |
| 最近记录: |