.NET/C#字典锁定协议

.NET/C#字典锁定协议,c#,dictionary,C#,Dictionary,我需要准确理解.NET字典集合的锁定和并发问题,而不是ConcurrentDictionary。假设我有一个定义为key=string,value=SomeOtherRandomClass的字典 在调用TryGetValue(“abc”)期间,是否必须对整个字典进行写锁定 如果可以保证在调用TryGetValue的过程中不会添加/删除任何键,那么是否仍需要对整个字典进行写锁定 如果成功调用TryGetValue,在修改相应的值(SomeOtherClass)时,是否必须锁定整个字典?或者只是那个

我需要准确理解.NET字典集合的锁定和并发问题,而不是ConcurrentDictionary。假设我有一个定义为key=string,value=SomeOtherRandomClass的字典

  • 在调用TryGetValue(“abc”)期间,是否必须对整个字典进行写锁定

  • 如果可以保证在调用TryGetValue的过程中不会添加/删除任何键,那么是否仍需要对整个字典进行写锁定

  • 如果成功调用TryGetValue,在修改相应的值(SomeOtherClass)时,是否必须锁定整个字典?或者只是那个特定的键,这样两个人就不能同时更新同一个(SomeOtherClass)


  • 我认为最合乎逻辑的答案是是肯定的、否定的,然后是否定的和肯定的。但我想绝对肯定。但是我可以想象,在实现中,对#1的答案是否定的。

    字典
    并没有考虑多线程。如果一个
    字典
    实例上的每个操作(读操作和写操作)将被多个线程访问,则必须锁定(最好是在
    字典
    SyncRoot
    属性上),否则就有损坏
    字典
    的风险。没有只锁定一把特定钥匙的设施

    但是,
    字典
    并不关心其值的内部结构,因此,一旦获得了值,在读取或修改值本身时就不需要将
    字典
    锁定,除非多个线程也将访问每个值(但是,您可以只锁定该值而不受影响)。这一切都取决于应用程序的要求,但您需要使用
    ConcurrentDictionary
    执行相同的工作

    还要注意的是,
    ConcurrentDictionary
    仅保护单个操作。如果两个线程尝试获取某个密钥的值,并将该密钥的值更新为比以前多一个值,则仍会存在争用条件,而不会手动锁定读写操作

    在调用TryGetValue(“abc”)期间,是否必须对整个字典进行写锁定

    是的,因为字典的实现不是线程安全的

    如果可以保证在调用TryGetValue的过程中不会添加/删除任何键,那么是否仍需要对整个字典进行写锁定

    不,这是不可能的,是的,它仍然需要被写锁定。我不知道“整个字典”是什么意思……你需要一个排他锁,防止两个线程在同一个字典中执行代码。这是因为字典的实现不是线程安全的

    如果成功调用TryGetValue,是否必须在修改相应的值(SomeOtherClass)时锁定整个字典?或者仅锁定该特定键,以便两个人不能同时更新同一个(SomeOtherClass)


    如果您正在修改值本身(例如,您调用
    字典[key]=value
    )然后是,它必须被锁定。如果值是引用类型,并且您不修改引用,而只是修改被引用的对象,则不需要锁定字典,因为您没有执行字典的任何代码,这不是线程安全的。

    最简单的解决方案是只使用
    ConcurrentDictionary。使用它而不是试图重新发明轮子有什么具体问题?1)是的。2) 不,但保证这种情况的方法是锁定整个字典(请参见1)。3) 这在某种程度上取决于您正在尝试做什么,实际上,
    ConcurrencyDictionary
    对您没有帮助。我想是的,不,不,但是。在并发环境中,几乎任何查找都必须对整个字典进行写锁定(但可能会发生多个并发查找),任何写操作都必须进行读/写锁定。一旦您从字典中取出了对象,为了对该对象进行更改,您只需要锁定对该特定对象的访问,尽管另一个线程可以替换密钥并将其完全从字典中删除。不过,API并不能保证这一切。使用ConcurrentDictionary是确保您安全的唯一方法。您是否阅读了文档中关于如何从多个线程访问该类型的说明?它明确地回答了所有这些问题。我同意@MattBurland的观点。如果您要问这些问题,您应该使用
    ConcurrentDictionary
    。好的,我确实看到了,但是如果您所需记录的物理位置是通过对键应用哈希函数确定的,并且如果目标值的地址无法更改,我看不出它是如何移动的——那么我看不出插入/删除其他键如何移动目标记录的地址。@词典的其他变异可能导致需要调整备份数组的大小,导致所有数据移动到新位置。好的,谢谢你,我理解。但这意味着——如果支持数组可以随时调整大小——如果我有以下逻辑:哦,对不起。假设(1)TryGetValue成功,并且我有了所需的键和值。现在假设为了论证(2),我必须对(其他类)的值进行十分钟的计算。如果所有数据都可以移动,那么这意味着我必须在整个十分钟内锁定整个字典,不?@lhs:在调整大小期间,将在
    字典中移动的数据只是对值的引用-值本身不受影响。因此,在处理值时(在从
    字典
    获得值后,在锁定状态下),您不必固有地持有锁。但该方法保证是安全的。