C# 什么';ConcurrentDictionary和ImmutableDictionary的区别是什么?

C# 什么';ConcurrentDictionary和ImmutableDictionary的区别是什么?,c#,.net,multithreading,dictionary,C#,.net,Multithreading,Dictionary,我正在读C#Cookbook中的Concurrency,这本书告诉我: ConcurrentDictionary在您有多个 线程读取和写入共享集合。如果更新是 不是常量(如果它们更罕见),而不是ImmutableDictionary 也许是更好的选择 我知道添加或删除一个大的不可变集合可能会很慢,我的问题是,它们之间还有其他区别吗?既然它们都是线程安全的,为什么在更新不是恒定的情况下,ImmutableDictionary是一个更好的选择?不可变不能更改,也就是说,没有添加/删除可以更改现有的字

我正在读C#Cookbook中的Concurrency,这本书告诉我:

ConcurrentDictionary
在您有多个 线程读取和写入共享集合。如果更新是 不是常量(如果它们更罕见),而不是
ImmutableDictionary
也许是更好的选择


我知道添加或删除一个大的不可变集合可能会很慢,我的问题是,它们之间还有其他区别吗?既然它们都是线程安全的,为什么在更新不是恒定的情况下,
ImmutableDictionary
是一个更好的选择?

不可变不能更改,也就是说,没有添加/删除可以更改现有的字典,而是创建一个新的字典来发送除已删除项以外的所有项。并发在与不变性无关的
lock{}
语句上进行。锁是管理多个线程对同一内存块(即同一对象)执行的写操作所必需的。

这两个类
ConcurrentDictionary
ImmutableDictionary
只是因为简单的原因而进行了比较,它们都是线程安全的


但是,对于多线程使用
ImmutableDictionary
不是一个好主意。它被设计用来表示应该加载一次的数据,以后不应该更改/修改。任何修改都会导致创建
ImmutableDictionary
的新实例,这不是真正有效的。

A
ConcurrentDictionary
不是不可变的。如果需要线程安全字典,请使用
ConcurrentDictionary
。如果您需要一个不可变的字典,请使用
不可变的字典
,这只是线程安全的副作用(如果您无法修改原始实例,则不存在多线程问题)。@TimSchmelter我可以理解这一点。但是,当更新不是恒定的时,为什么ImmutableDictionary是一个更好的选择呢?也许immutable dictionary在这种情况下有更好的性能?这是一个更好的选择,因为它保证它永远不会被修改(如果这很重要的话)。ConcurrentDictionary永远不能保证这一点。但它允许使用
Add
Remove
创建新的ImmutableDictionary实例methods@TimSchmelter明白了,谢谢。我不明白这个答案。然后问一个问题。什么意思:“创建一个新的,除了已删除的邮件外,所有邮件都发送”?什么是“并发在lock{}语句上进行”?(
ConcurrentDictionary
不使用
lock
,您也不需要自己使用)
ImmutableDictionary
也不需要
锁(/afaik),而且线程安全吗?真的吗?尝试反编译并查看TryRemoveInternal的功能。关于通过删除获得新实例:每当您决定更改不可变对象的内容时,您永远不会修改现有的实例,您将获得一个包含所有项目**的新实例,但**您删除的项目除外。因此,一切都不会改变:看起来是这样,但实际上你创造了新的对象。@Serejabogolobov好的,我现在明白你的意思了。顺便说一句,其他人不会看到错误发布的答案,不要担心:)正确实现的不可变类型非常适合使用。唯一的问题是C#的实现远远不能被接受。这本书说,这并没有那么浪费,因为@Tim Schmelter提到过,不可变集合共享它们的大部分内存,不可变性保证集合永远不会被修改,所以-我同意,使用不可变类型的线程同步肯定不会有任何问题。另一个问题是关于C#实现的,而不是线程安全集合的一般最佳实践。@Nico,这里是比较,这里是。简言之,不可变字典在大多数情况下比字典慢,同时ConcurrentDictionary具有更好或相同的性能。线程安全方面仅与真正的不可变类型相关。我已经看到了关于为什么可以调用没有可观察到的更改的类型可以被称为不可变的,即使内部发生了变化。这些对象显然不是隐式线程安全的,因为它们是“不可变的”