锁定HashSet并发

编程入门 行业动态 更新时间:2024-10-26 18:28:19
本文介绍了锁定HashSet并发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

使用 HashSet< string> 进行检查时,是否曾处理过某项(即仅 Add 和包含)。而且,当Contains返回false时,即使它是在...之前添加的,也没有关系。

When using a HashSet<string> to check, whether an item was handled before (i.e. only Add and Contains is used). Furthermore it is not relevant, when Contains returns false, even though it was added before ...

我遇到了以下未锁定的异常:

I encountered following exception without locking:

[IndexOutOfRangeException:索引超出数组的范围。] System.Collections.Generic.HashSet`1.AddIfNotPresent(T value)+6108128

[IndexOutOfRangeException: Index was outside the bounds of the array.] System.Collections.Generic.HashSet`1.AddIfNotPresent(T value) +6108128

仅锁定添加调用就足够了吗?

Is it sufficient, to lock only the Add call?

以下似乎永远有效-但这不是证明...

Following seems to work forever - but that is not a proof...

HashSet<string> hashSet = new HashSet<string>(); Parallel.ForEach(GetString(), h => { hashSet.Contains(h); lock(hashSetLock) { hashSet.Add(h); } hashSet.Contains(h); });

准确地说:我知道调用包含不带锁。我的问题是(接受错误肯定)以上代码是否可能引发异常或破坏基础数据结构(= HashSet)的内部状态。

To make it precise: I know that it is not thread-safe to call Contains without a lock. My question is (accepting false positives) if the above code could throw an exception or could destroy the internal state of the underlying data structure (=HashSet).

推荐答案

否,仅锁定 Add 是不够的。

事实它不会崩溃只是告诉您它在测试期间没有崩溃。

The fact that it doesn't crash only tells you that it didn't crash during your test.

您不能保证:

  • 将来不会崩溃
  • 它将产生正确的结果

非线程安全的数据结构不能保证以多线程方式使用。

A non-threadsafe data structure has no guarantees whatsoever if used in a multithreaded fashion.

您需要:

  • 每次调用时锁定
  • 使用线程安全数据结构,该结构已构建为支持此方案

如果您使用的数据结构与哈希集不同,例如字典,则可能甚至需要锁定多语句,因为可能仍然失败:

If you use a different data structure than a hashset, like a dictionary, you may even need to lock multi-statements, because this may still fail:

lock (dLock) if (d.ContainsKey("test")) return; var value = ExpensiveCallToObtainValue(); lock (dLock) d.Add("test", value);

在 ContainsKey 的调用与调用之间添加另一个线程可能已经插入了该键。

Between the call to ContainsKey and the call to Add another thread may have already inserted that key.

要正确处理此问题,而无需使用线程安全的数据结构,将两个操作都包含在同一锁内:

To handle this correctly, without using a threadsafe data structure, is contain both operations inside the same lock:

lock (dLock) { if (!d.ContainsKey("test")) d.Add("test", ExpensiveCallToObtainValue()); }

更多推荐

锁定HashSet并发

本文发布于:2023-11-10 01:52:29,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1574031.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:HashSet

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!