0

在多线程应用程序中,我有一个由多个线程访问的字典,用于获取特定键的值。还有一种使用 Quartz.Net 的机制来更新这个字典。我正在尝试找到使更新后的字典可用于以线程安全方式阅读的最佳方法。最初,我将 ReadWriterLockSlim 视为一种解决方案,但当我搜索可能的性能损失时,我可能遇到了 Interlocked.Exchange 和可用于对象的重载。所以我的问题是,它可以在这种情况下使用吗?我提供了它的用法的代码示例。

非常感谢

public class SingletonDictionaryHolder
{
    private Dictionary<string, Person> MyDictionary;

    public Person GetPerson(string key)
    {
        return MyDictionary[key];
    }

    public void UpdateDictionary(Dictionary<string, Person> updated)
    {
        Interlocked.Exchange(ref MyDictionary, updated);
    }
}  

 

编辑:

由于有一个downvote,我添加了一些更多信息:

此处介绍了另一个相关问题:https ://softwareengineering.stackexchange.com/questions/294514/does-readerwriterlockslim-provide-thread-safety-and-speed-efficiency-compared-t

请注意以下段落:“如果写入很少,您可以通过将集合视为不可变并在它更改时生成一个全新的列表来获得更好的性能。然后您可以使用 Interlocked.CompareExchange 更新对线程中列表的引用-安全的方式。这应该可以防止读者需要制作防御性副本(如果阅读比写作更普遍,这应该是一个巨大的胜利)并消除对锁定的需要。

关于 Intelocked.CompareExchange 方法,这里提供了一个见解:Using Interlocked.CompareExchange with a class

请注意,正确的架构设计是使用默认线程安全的 MemoryCache 和 pub/sub 机制来反映缓存项的更改 - 但是它不是由我设计的,我怀疑是否有希望改变不久的将来。

4

1 回答 1

0

在真正有用的评论的指导下回答我自己的问题。线程安全不需要 Interlock.Exchange,因为引用分配在所有 .Net 平台中都是线程安全的。

所以更新的对象可以安全地分配给原始对象。更新后将访问相关对象的线程将获得新的对象,这对我的场景来说完全没问题。

对于遇到这个问题的未来读者,请看一下: 引用分配是原子的,那么为什么需要 Interlocked.Exchange(ref Object, Object)?

于 2020-12-13T08:48:35.223 回答