在某些情况下,我真的很喜欢使用Guava's Striped类。
C#中是否存在等效内容?
答案 0 :(得分:10)
看起来没有直接的等价物,但是有一些无锁的线程安全收集选项(我不确定你想要实现的目标,所以我可以&#39 ;如果它们适用于您的场景,请说。)看看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
答案 1 :(得分:6)
我认为你能做的最好就是实现自己的,因为所有的dotnet框架类型只为整个列表提供了一个lock
。
要做到这一点,您可以使用GetHashCode()
函数,模数(%
)与您想要的条带数。并将其用作Tuple<TLock, List<T>>[]
的索引,其中TLock可以是System.Threading
命名空间中定义的任何类型的锁,T是您要存储/访问的类型。
通过此,您可以决定如何存储条带。有一些选项,如HashSet
(因为你已经使用了一些比特来计算条带索引,因此效率很低),SortedSet
,List
,Array
。
答案 2 :(得分:1)
您是否尝试过NuGet中的Tamarind? 它是Google的Guava库的C#端口
答案 3 :(得分:1)
我认为ConcurrentDictionary可以存档类似的结果。
根据他们的文件:
所有这些操作都是原子的,并且对于ConcurrentDictionary类的所有其他操作都是线程安全的。唯一的例外是接受委托的方法,即AddOrUpdate和GetOrAdd。对于字典的修改和写入操作,ConcurrentDictionary使用细粒度锁定来确保线程安全。 (对字典的读取操作是以无锁方式执行的。)但是,这些方法的委托在锁外部调用,以避免在锁定下执行未知代码时可能出现的问题。因此,这些代理执行的代码不受操作原子性的影响。
如您所见,读取操作是无锁定的。这将允许您在其他人插入时不阻止线程读取。