c# – 何时在.net中锁定线程安全的集合? (什么时候不锁?)

codeday· 2019-11-15
本文来自 codeday ,作者 codeday
好的,我读过Thread safe collections in .NETWhy lock Thread safe collections?.

前一个问题是以java为中心,不回答我的问题,后面的问题的答案告诉我不需要锁定集合,因为它们应该是线程安全的. (这是我的想法)

现在回答我的问题,
我看到很多开发人员(在github和我的组织中)已经开始使用新的线程安全集合.但是,通常他们不会在读取和放大器周围移除锁定.写操作.
我不明白这一点.不是一个线程安全的集合……好吧,线程安全吗?

不锁定线程安全集合会带来什么影响?

编辑:PS:这是我的情况,

我有很多课程,其中一些课程有一个属性.我经常需要检查给定类型是否具有该属性(当然使用反射).这在性能上可能很昂贵.所以决定使用ConcurrentDictionary< string,bool>创建一个缓存. string是typeName,bool指定它是否具有该属性.首先,缓存是空的,计划是在需要时继续添加缓存.我遇到了ConcurrentDictionary的GetOrAdd()方法.我的问题是一样的,如果我应该调用这个方法而不锁定?

MSDN的评论说:

If you call GetOrAdd simultaneously on different threads,
addValueFactory may be called multiple times, but its key/value pair
might not be added to the dictionary for every call.

最佳答案
您不应该锁定线程安全集合,它会公开方法来更新已锁定的集合,并按预期使用它们.

如果要在集合上打开枚举器时阻止修改(提供的线程安全集合允许修改),则线程安全集合可能与您的需求不匹配.如果是这种情况,您最好使用常规集合并将其锁定在任何地方.线程安全集合的内部锁定不公开.

很难回答关于不锁定线程安全集合的含义.您不需要锁定线程安全的集合,但您可能必须锁定执行多项操作的代码.没有看到代码很难说.

是的,该方法是线程安全的,但如果您同时为同一个键点击Add,它可能会多次调用AddValueFactory.最后,只会添加其中一个值,其他值将被丢弃.这可能不是一个问题…你必须检查你达到这种情况的频率,但我认为这并不常见,你可以忍受可能永远不会发生的边缘情况下的性能损失.

您也可以在静态ctor中或在需要之前构建您的词典.这样,dictionnary就会填充一次,你就不会写它了.然后字典是只读的,您不需要任何锁定也不需要线程安全集合.