执行 AsyncLocal<>值需要是线程安全的吗? [英] Do AsyncLocal&lt;&gt; values need to be thread-safe?

查看:33
本文介绍了执行 AsyncLocal<>值需要是线程安全的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在最近的 PR 评论中提出了一个问题,关于 AsyncLocal> 是否应该使用 ConcurrentDictionary<>.我的想法是它不需要,因为多个线程不会同时访问 AsyncLocal 值.但我想确定.

A question came up in a recent PR review about whether or not an AsyncLocal<IDictionary<>> should use ConcurrentDictionary<>. My thinking is that it does not need to because an AsyncLocal value won't be accessed by multiple threads at the same time. But I want to be certain.

我们是否需要担心保存在 AsyncLocal 中的对象的线程安全性?请解释为什么或为什么不.演示断言答案的单元测试的加分项.

Do we need to worry about thread-safety of objects kept in AsyncLocal? Please explain why or why not. Bonus points for a unit test demonstrating the asserted answer.

推荐答案

AsyncLocal 可用于异步控制流中的所有线程.

AsyncLocal is available to all threads in an asynchronous control flow.

让我们以这个例子为例:

Let's take this example:

using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp15
{
    class Program
    {

        static AsyncLocal<string> _asyncLocalString = new AsyncLocal<string>();

        static async Task Main(string[] args)
        {
            _asyncLocalString.Value = "TestString";

            var tasks = Enumerable.Range(0, 10).Select(_ => GetString());
            var results = await Task.WhenAll(tasks);
        }

        private static async Task<string> GetString()
        {
            await Task.Yield();
            return _asyncLocalString.Value + Thread.CurrentThread.ManagedThreadId;
        }
    }
}

这里多个线程可以访问值TestString";同时.

Here multiple threads can access the value "TestString" at the same time.

此外,一旦该值从 Async local 中提取出来,就需要像对待任何其他引用一样对待它.如果在回调中使用,返回给调用者,在闭包中捕获等,它可以暴露给其他线程.使用引用类型时,可以在外部修改值并可能出现竞争条件.

Additionally, once the value is pulled out of Async local it needs to be treated just like any other reference. If it is used in callbacks, returned to the caller, captured in a closure etc, it can be exposed to other threads. With reference types, values could be modified externally and race conditions could occur.

更新:这是一个字典的例子:

using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp15
{
    class Program
    {

        static AsyncLocal<Dictionary<string, int>> _asyncLocalDict = new AsyncLocal<Dictionary<string, int>>();

        static async Task Main(string[] args)
        {
            _asyncLocalDict.Value = new Dictionary<string, int>();

            var tasks = Enumerable.Range(0, 10).Select(_ => Race());
            await Task.WhenAll(tasks);
        }

        private static async Task Race()
        {
            await Task.Yield();
            var dict = _asyncLocalDict.Value;
            if (!dict.ContainsKey("race")) dict["race"] = 0;
            dict["race"]++;
        }
    }
}

这篇关于执行 AsyncLocal<>值需要是线程安全的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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