异步代码,共享变量,线程池线程和线程安全 [英] Asynchronous code, shared variables, thread-pool threads and thread safety

查看:183
本文介绍了异步代码,共享变量,线程池线程和线程安全的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆