【问题标题】:Returning a dictionary in c# in a multi-threaded environment在多线程环境中返回 C# 中的字典
【发布时间】:2012-02-17 12:47:29
【问题描述】:

我已经声明了一本字典:

Dictionary<String, Dictionary<String, String>> values;

我有一个获取特定索引处的字典:

public Dictionary<String,String> get(String idx)
{
    lock (_lock)
    {
        return values[moduleName];
    }
}

如您所见,我在多线程环境中工作。 我的问题是我是否需要返回我的字典副本才能像这样实现线程安全:

public Dictionary<String,String> get(String idx)
{
    lock (_lock)
    {
        return new Dictionary<string, string>(values[moduleName]);
    }
}

如果我不这样做,调用 getter 的类会收到一份副本(因此,如果我从我的 Dictionary&lt;String, Dictionary&lt;String, String&gt;&gt; 中删除此字典,它是否仍然有效)?

干杯,

蒂埃里。

【问题讨论】:

  • 你可能根本不应该返回字典,但如果你这样做了,那么是的,你需要在监视器内进行复制。你能描述一下这个结构的目的是什么吗?
  • 我必须存储按模块排序的设置。所以每个模块都有一个设置字典,并且必须能够获取它们。配置管理器保留所有这些模块,以便它们可以轻松更新。

标签: c# concurrency dictionary return


【解决方案1】:

Dictionary&lt;&gt; 不是线程安全的,但ConncurrentDictionary&lt;&gt; 是。

调用getter的类收到一个引用,这意味着如果你从values-Dictionary中删除它,它仍然存在,因为只要你在某处有引用,GC就不会清理它,你就可以'不再使用 getter 了。

基本上这意味着您在使用Dictionary&lt;&gt;时有两种可能性:

  • 返回副本:这是个坏主意,因为如果您更改配置,您的应用中就会有两种不同的配置“活着”
  • 锁定实例:这将使其成为线程安全的,但随后使用ConcurrentDictionary&lt;&gt;,因为它完全适合您

【讨论】:

  • 记住。从 ConcurrentDictionary 检索的项目不会自动线程保存!
  • 感谢您的回复,帮助我更好地理解了。
【解决方案2】:

如果您真的需要返回字典本身,那么您将需要制定线程如何锁定它的规则(很脆弱,如果有一个没有的情况怎么办?),在只读方式(字典对于只读来说是线程安全的,但请注意,这假定类私有的代码也不再写入它),使用线程安全字典(ConcurrentDictionary 使用条带锁定,我的ThreadSafeDictionary 使用无锁方法,并且有不同的场景,其中一个击败另一个),或者按照您的建议制作副本。

但是,如果您公开一个方法来检索或设置由两个键找到的最终字符串,枚举由一个键找到的二级键,等等,那么您不仅可以控制锁定在一个地方完成,但它在接口的清洁和从接口中释放实现方面具有其他优势(例如,您可以从基于锁的移动到使用线程安全字典,或者相反,而不影响调用代码) .

【讨论】:

    【解决方案3】:

    如果您不返回副本,调用者将能够更改字典,但这不是线程安全问题。

    还有一个线程安全问题,因为您没有公开任何锁来同步写入和读取。例如,当阅读器线程在同一个实例上工作时,您的编写器线程可以添加/删除一个值。

    是的,您必须退回一份。

    【讨论】:

    • 您可以简单地记录使用字典的人必须将其锁定在某个地方。
    • 感谢您的回复,在我的情况下,调用者和包含类都可能访问返回字典的值,因此我将不得不去复制或并发字典。
    • @CodingBarfield 是的,但是您应该公开用于填充字典的同步锁对象,以便每个人都锁定同一个对象。不建议锁定字典本身,但这是另一个话题。
    • @CodingBarfield:我当然建议不要这样做。人们可能会忘记这样做,并且线程问题可能难以调试。这也可能引入死锁,因为同步对象需要是公共的。而纪尧姆,公开锁定对象在功能上完全等同于锁定对象本身。
    • 我说过要以某种方式锁定字典。无论您是使用字典来锁定它还是实施黑盒锁定,我都可以。我会选择最终用户/程序员无法回避的实现。
    猜你喜欢
    • 2010-12-08
    • 2018-06-17
    • 1970-01-01
    • 1970-01-01
    • 2013-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多