C# 并发字典对象读取/更新线程安全问题

问题描述

在下面的代码中,我有一个并发字典,用于存储单个键/值对,其中值是一个字符串集合。

我将读取和更新来自不同线程的单个键/值对中的字符串。

我知道,如果一个线程在另一个线程可能完成读取之前更改了一个值,则并发字典并不完全是线程安全的。但同样我不确定字符串值是否真的涉及到这个话题,有人可以请教吗?

还值得一提的是,虽然我把这个“GetRunTimeVariables”方法放到了依赖注入的接口中,但由于应用启动阶段和OIDC事件登录/退出的阶段,我实际上不能一直使用DI来访问这个方法我需要访问不能使用依赖注入的类中的字典值,所以本质上我可以在应用程序的整个生命周期中根据需要从 nay 方法访问这个字典。

最后,我不确定将此方法推入接口是否有任何好处,另一种选择只是在每次需要时新建对此类的引用,对此有一些想法将不胜感激。

public class RunTimeSettings : IRunTimeSettings
{
    // Create a new static instance of the RunTimeSettingsDictionary that is used for storing settings that are used for quick
    // access during the life time of the application. VarIoUs other classes/threads will read/update the parameters.
    public static readonly ConcurrentDictionary<int,RunTimeVariables> RunTimeSettingsDictionary = new ConcurrentDictionary<int,RunTimeVariables>();

    public object GetRunTimeVariables()
    {
        dynamic settings = new RunTimeVariables();

        if (RunTimeSettingsDictionary.TryGetValue(1,out RunTimeVariables runTimeVariables))
        {
            settings.Sitename = runTimeVariables.SiteName;                
            settings.Street = runTimeVariables.Street;
            settings.City = runTimeVariables.City;
            settings.Country = runTimeVariables.Country;
            settings.PostCode = runTimeVariables.PostCode;
            settings.Latitude = runTimeVariables.Latitude;
            settings.Longitude = runTimeVariables.Longitude;
        }

        return settings;
    }
}

字符串值的类:

public class RunTimeVariables
{
    public bool InstalledLocationConfigured { get; set; }
    public string SiteName { get; set; }
    public string Street { get; set; }
    public string City { get; set; }
    public string Country { get; set; }
    public string PostCode { get; set; }
    public string Latitude { get; set; }
    public string Longitude { get; set; }
}

解决方法

System.String 类型(C# 的经典 string)是不可变的。没有人可以修改 String 的“内容”。任何人都可以使属性引用不同 String

但实际上,您在这里遇到的唯一问题是各种值可能不同步。您有各种相关的属性。如果一个线程正在修改对象而另一个线程正在读取它,则读取线程可能会看到“旧”版本的一些属性和“新”版本的一些属性。如果曾经写入 ConcurrentDictionary 的对象没有改变(至少作为业务规则是“不可变的”),这不是一个大问题。显然,正确的解决方案是让 RuntimeVariables 成为不可变对象(例如仅由在实例化时初始化的 readonly 字段组成)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...