【问题标题】:Is there an equivalent for Guava Striped-Class in C#?C# 中的 Guava Striped-Class 是否有等价物?
【发布时间】:2015-08-17 09:22:32
【问题描述】:

在某些情况下,我真的很喜欢使用Guava's Striped 类。

C# 中是否有等价物?

【问题讨论】:

  • 难道你不能通过拥有一组n 对象并将每个x 锁定在arr[x.GetHashCode() % n] 上来接近吗?

标签: c# concurrency guava


【解决方案1】:

看起来没有直接的等价物,但有一些无锁线程安全集合选项(我不确定你想要实现什么,所以我不能说它们是否适用你的场景)。看看System.Collections.Concurrent Namespace

特别是,ConcurrentBag、ConcurrentQueue、ConcurrentStack 和 ConcurrentDictionary 都有不同的锁定/无锁线程安全策略。一些在this blog post中进行了解释。

您也许可以通过Partitioner 类获得您想要的,尽管我不确定具体的实现方式。

@Behrooz 说所有 .net 框架类型只对整个列表使用一个锁是不正确的。看看source for ConcurrentDictionary。第 71 行表明这个类是使用多个锁实现的。

如果你真的想,你可以写你自己的版本。 Guava Striped 的来源是:https://github.com/google/guava/blob/master/guava/src/com/google/common/util/concurrent/Striped.java

【讨论】:

  • 错了,第 1863、1873、1875 行。顺便说一句,他们没有任何其他的死锁预防机制。
  • @Behrooz 我认为您可能读错了该代码。除非 AcquireLocks 方法只用于获取单个锁(这似乎毫无意义,但我不知道)它显然支持多个锁。第 1875 行的评论说 m_locks 集合不会增长,并不是说它只有 1 个锁。
  • 实际上,我在前几年已经多次阅读该代码。对于不需要它的操作,它锁定太多。并且它将存储桶 0 锁定用于在锁定时显然不需要锁定它的操作(例如获取计数),这会导致具有多个读取器/写入器的小型集合中的大量减速。
  • 他们实现了主锁,他们决定不需要声明额外的变量。糟糕的设计,IMO。
  • 感谢您的回答。我会让赏金自动奖励 - 应该是你的。 :)
【解决方案2】:

我认为你能做的最好的事情就是实现你自己的,因为所有 dotnet 框架类型只为整个列表提供一个 lock
为此,您可以使用 GetHashCode() 函数,模数(%)它与您想要的条纹数。并将其用作Tuple<TLock, List<T>>[] 的索引,其中 TLock 可以是在 System.Threading 命名空间中定义的任何类型的锁,而 T 是您要存储/访问的类型。
有了这个,您可以决定如何存储您的条纹。有诸如HashSet(在您的情况下效率低,因为您已经使用一些位来计算条带索引)、SortedSetListArray 之类的选择。

顺便说一句,谢谢你的问题,它会帮助我解决我遇到的问题。

【讨论】:

  • 感谢您的回答! +1
【解决方案3】:

您是否尝试过来自 NuGet 的 Tamarind
它是谷歌 Guava 库的 C# 端口

【讨论】:

【解决方案4】:

我认为ConcurrentDictionary 可以存档类似的结果。

根据他们的文档:

所有这些操作都是原子的,并且对于 ConcurrentDictionary 类上的所有其他操作都是线程安全的。唯一的例外是接受委托的方法,即 AddOrUpdate 和 GetOrAdd。对于字典的修改和写入操作,ConcurrentDictionary 使用细粒度锁定来确保线程安全。 (对字典的读取操作以无锁方式执行。)但是,这些方法的委托在锁外调用,以避免在锁下执行未知代码可能出现的问题。因此,这些委托执行的代码不受操作的原子性影响。

如您所见,读操作是无锁的。例如,这将允许您在其他线程插入时不会阻止线程读取。

【讨论】:

  • 我认为你没有得到 Guava 的 Striped 类的意图。
猜你喜欢
  • 2022-09-23
  • 1970-01-01
  • 2013-06-21
  • 1970-01-01
  • 2012-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多