【问题标题】:Thread safety of a Dictionary<TKey, TValue>Dictionary<TKey, TValue> 的线程安全
【发布时间】:2011-01-03 20:34:04
【问题描述】:

如果我初始化一个通用字典一次,并且不允许进一步的添加/更新/删除,那么在没有锁定的情况下让多个线程读取它是否安全(假设字典在读取器启动之前被初始化)?

非泛型 HashTable 的帮助中有一条注释说它对多个读者是安全的,但我没有看到泛型字典的类似内容。

【问题讨论】:

    标签: c#


    【解决方案1】:

    供您将来参考,文档在这里:

    http://msdn.microsoft.com/en-us/library/xfhwa508.aspx

    上面写着:

    字典 可以支持多个阅读器 同时,只要 集合未修改。即使是这样, 通过集合枚举是 本质上不是线程安全的 程序。在极少数情况下 枚举与写竞争 访问,集合必须是 在整个枚举期间锁定。 允许访问集合 通过多个线程进行阅读和 写,你必须实现你自己的 同步。

    【讨论】:

    • 只是想确保我正确理解引用段落的“即使如此......”部分。是否真的:(1)如果字典不再被修改(如OP的问题中所述),那么枚举也不会成为问题。 (2) 如果字典将来可能会被修改,那么即使ConcurrentDictionary 枚举也是“本质上不是线程安全的过程”。对吗?
    • @RayLuo:一般情况下,无论是多线程还是单线程,都不允许在枚举“进行中”时修改集合。
    • 并发框架集合(例如,System.Collections.Concurrent.ConcurrentDictionary)通常允许在枚举期间进行修改。但是,他们通过制作集合的副本并让您枚举副本来实现此目的。并且在制作副本时整个收藏都被锁定。框架工程师可能会争辩说,这意味着您没有在枚举“飞行”时修改集合(因为在引擎盖下,整个事情在枚举“飞行”时被锁定),但从框架用户的角度来看,枚举正在进行中。
    • 感谢 Eric 和@Brian 的洞察力。对于它的价值,这里引用Dictionary.GetEnumerator():“只要集合保持不变,枚举器就保持有效。如果对集合进行更改,例如添加、修改或删除元素,枚举器将不可恢复地失效并且它的行为是未定义的。枚举器没有对集合的独占访问权;" ConcurrentDictionary 枚举 differently,顺便说一句。
    【解决方案2】:

    是的,如果您不再修改字典是安全的。线程安全只是读/写场景中的问题

    【讨论】:

    • 不过,您必须考虑内部状态。在外部,您可能只从字典中读取一个值。但是,您不知道在检索期间可能会发生哪些状态转换。
    • OP @JMarsch 在上面发表评论并获得 10 票赞成。那么“内部状态”会如何影响 OP 的场景呢? If I initialize a generic dictionary once, and no further adds/updates/removes are allowed, is it safe to have multiple threads reading from it with no locking (assuming that the dictionary is initialized before the readers are started)? 还可以吗
    • 对于字典,是的,Eric Lippert 的答案是正确的。从我的评论中要记住的重要一点是,通常,如果您只对其进行读取,则假设数据结构是线程安全的是不够的,因为您不知道读取如何影响内部状态。就字典而言,事实证明,读取操作确实是安全的,只要在并发读取器使用它时没有人写入它。所以在你的例子中,你初始化一次,然后只读取它,你是安全的。
    • 感谢您的澄清。因此,从您的第一条评论中可采取的行动是“理想情况下,仔细检查数据结构的文档或源代码,以查看读取是否是线程安全的”,因为直觉上人们会假设读取是线程安全的,所以当事实并非如此,数据结构开发人员希望将其记录下来。 (为了完整起见,我做了一个脑力练习,并想出了一个可以根据读取频率动态调整其结构的霍夫曼树,可能不是线程安全的读取。也许这 10 位支持者也做了他们的练习。)跨度>
    猜你喜欢
    • 1970-01-01
    • 2018-06-06
    • 1970-01-01
    • 1970-01-01
    • 2016-06-14
    • 2011-04-11
    • 1970-01-01
    • 2011-01-16
    相关资源
    最近更新 更多