当前位置: 首页 > 编程语言 > C#

锁定集合和syncRoot有什么缺点?分享

时间:2023-04-10 11:12:47 C#

锁定集合与syncRoot的任何缺点?我想知道锁定List、HashSet或Dictionary等集合而不是简单对象是否有任何缺点。注意:在下面的示例中,这是唯一发生锁定的地方,它不会从多个地方锁定,但它可以线程调用静态方法。此外,永远不会在GetSomething方法之外访问_dict。我当前的代码如下所示:privatestaticreadonlyDictionary_dict=newDictionary();公共静态字符串GetSomething(字符串键){字符串结果;if(!_dict.TryGetValue(key,outresult)){lock(_dict){if(!_dict.TryGetValue(key,outresult)){_dict[key]=result=CalculateSomethingExpensive(key);}}}返回结果;}另一位开发人员告诉我锁定集合会导致问题,但我持怀疑态度。如果我这样做,我的代码会更有效率吗?privatestaticreadonlyDictionary_dict=newDictionary();私有静态只读对象_syncRoot=newobject();公共静态字符串GetSomething(字符串键){字符串结果;if(!_dict.TryGetValue(key,outresult)){lock(_syncRoot){if(!_dict.TryGetValue(key,outresult)){_dict[key]=result=CalculateSomethingExpensive(key);}}}返回结果;如果您要向外界公开集合,那么,这可能是一个问题。一般的建议是锁定你独有的东西,不要意外地被你影响范围之外的代码锁定。这就是为什么通常最好锁定您从未考虑过公开的内容(即为此目的创建的特定锁定对象)。这样,当您的记忆出现故障时,您永远不会得到意想不到的结果。更直接地回答您的问题:将另一个对象添加到混合中永远不会更有效,但是将通常被认为是良好的编码实践放在一些可感知但未衡量的效率可能过早发生的选择之前。我赞成最佳实践,直到它明显造成瓶颈。在这种情况下,我会锁定集合;锁的用途与集合直接相关,与任何其他对象无关,因此将其用作锁对象有一定程度的自我注意。虽然我会做出改变。我在文档中没有发现TryGetValue是线程安全的,如果在字典处于无效状态时调用它不会抛出异常(或更糟),因为它是添加新值的一半。由于它不是Primefaces,因此您在此处使用的双读模式(以避免获取锁所需的时间)并不安全。这必须更改为:privatestaticreadonlyDictionary_dict=newDictionary();公共静态字符串GetSomething(字符串键){字符串结果;lock(_dict){if(!_dict.TryGetValue(key,outresult)){_dict[key]=result=CalculateSomethingExpensive(key);}}返回结果;如果它可能涉及比不成功的更多的成功读取(因此需要写入),则使用ReaderWriterLockSlim将为那些读取性提供更好的并发性。编辑:我刚刚注意到你的问题不是关于偏好,而是关于效率。事实上,在整个系统中使用超过4个字节的内存(因为它是静态的)的效率差异绝对为零。这个决定不是关于效率,而是因为两者具有相同的技术优势(在这种情况下),这是关于你是否找到锁定集合或分离对象更好地向另一个开发人员(包括将来的你)表达你的意图。不能。只要不能从其他任何地方访问该变量,并且您可以保证只在此处使用锁定,就没有缺点。事实上,Monitor.Enter(这是C#中使用的锁)的文档就是这样做的。但是,作为一般规则,我仍然建议使用私有对象进行锁定。如果您将此对象暴露给任何其他代码,这通常更安全并且会保护您,因为您不会打开从其他代码锁定该对象的可能性。直接回答您的问题:不,您锁定的对象没有区别。.NET只关心它的引用,它们的工作方式与指针完全一样。将.NET锁想象成一个大的同步哈希表,其中的键是对象引用,值是一个布尔值,表示您可以进入监视器。如果两个线程锁到不同的对象(a!=b),它们可以同时进入锁的监视器,即使a.Equals(b)(这个很重要!!!)。但是如果他们锁定a和b,并且(a==b)一次只有一个在监视器中。只要您不在范围之外访问字典,就不会影响性能。如果dict在其他地方可见,其他用户代码可能会锁定它,即使它不一定需要(认为您的桌面是个傻瓜并锁定他在代码中找到的第一个随机对象)。希望得到帮助。我建议使用ICollection.SyncRoot对象来锁定而不是你自己的对象:以上是C#学习教程:锁定集合和syncRoot的任何缺点?如果分享的内容对你有用,需要了解更多C#学习教程,希望大家多多关注——privatestaticreadonlyDictionary_dict=newDictionary();私有静态只读对象_syncRoot=((ICollection)_dict)。同步根;本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: