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

问题描述

最近的PR评论中出现了一个问题,关于 AsyncLocal< IDictionary<> 是否应使用 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.

让我们举个例子:

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本地中拉出,则需要像对待其他任何引用一样对待它.如果在回调中使用,返回给调用者,在闭包中捕获等,则可以将其公开给其他线程.使用引用类型时,可以在外部修改值并可能出现竞争条件.

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.

更新:这是一个带有字典的示例:

Update:Here is an example with a dictionary:

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&lt;&gt;值需要是线程安全的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-14 07:39