相当于java';C#中的s ConcurrentHashMap?

相当于java';C#中的s ConcurrentHashMap?,c#,C#,有什么吗?C#(以及.NET的其他部分)有一个哈希表。。。它位于System.Collections中。我不确定java中的“并发”哈希映射是什么,但当只有一个编写器和任意数量的读取器时,哈希表应该是线程安全的。。。除此之外,您必须自己管理并发。我不熟悉您所说的ConcurrentHashMap。也许您可以定义它执行的功能,您也希望在C#中使用该功能 如果您只想保证集合对于并发访问是线程安全的,那么最好定义自己的锁策略来控制对它的访问 在早期版本的.NET framework中看到的Hashta

有什么吗?

C#(以及.NET的其他部分)有一个哈希表。。。它位于System.Collections中。我不确定java中的“并发”哈希映射是什么,但当只有一个编写器和任意数量的读取器时,哈希表应该是线程安全的。。。除此之外,您必须自己管理并发。

我不熟悉您所说的
ConcurrentHashMap
。也许您可以定义它执行的功能,您也希望在C#中使用该功能

如果您只想保证集合对于并发访问是线程安全的,那么最好定义自己的锁策略来控制对它的访问

在早期版本的.NET framework中看到的
Hashtable.synchronized(…)
方法已被删除(同时通过
System.Collections.Generic中的显式实现隐藏所有ICollection.SyncRoot实现)。这是因为,每当您锁定一个可公开访问的对象时,您就为其他调用者以您无法控制的方式锁定您的对象打开了可能性,因此死锁成为可能

此外,“同步”集合只能保证对单个成员的调用是安全的,但许多场景涉及包括许多成员在内的“事务”。考虑下面的例子:

if (collection.Contains(item))
    collection.Get(item);
map
对象(无论它是什么类型)可以保证
包含的
Get
方法都是线程安全的,但是它不能保证在调用
Get
时该项仍然包含在map中。相反,您应该使用如下代码:

private readonly object _mapLock = new object();

public void Method()
{
    lock (_mapLock)
    {
        if (collection.Contains(item))
            collection.Get(item);
    }
}

@奥斯卡建议使用
ReaderWriterLock
。此类的实现非常糟糕,性能比简单锁定差。如果您使用的是较新版本的框架,请改用
ReaderWriterLockSlim

ConcurrentHashMap的基本思想是它是线程安全的,不需要锁。 所以所有的“使用锁的想法”基本上就像你说的“使用Java”

在内部,您使用一些CAS(比较和交换)操作,并保证 线程如何运行某些不变量始终保持为真。既然你不互相排斥 (唯一的原子元素是硬件中的CAS操作),完全避免了死锁的可能性,通常也会获得一些性能增益。 当然,数据结构的实现要(复杂得多)多(这就是为什么准备好一个数据结构很酷,否则实现它甚至证明它是一件痛苦的事情) 它实际上可以处理更多线程)


我希望.NET框架中也有这样的东西。

有一个用于实现关联数组(又称哈希表)的通用字典类。最近微软推出了ConcurrentDictionary类:这可能就是你想要的。不过是.NET4+(

我正在寻找一个通用版本。有没有开源的lib?我什么都不知道,但请注意.Net的并行扩展。它们有一些并发集合类,但还没有字典实现。你能解释一下ConcurrentHashMap对我们这些不熟悉它的人有什么作用吗?应该复制吗另一方面,如果作者添加了一个导致哈希表重新刷新的add,我就不会期望读者的枚举数保持稳定。我在MSDN中读过一次,虽然我自己没有测试过。所以我希望它是真的,但我还没有证明它。MSDN:哈希表对于多个读者线程和单个wri来说是线程安全的ting thread.但是:枚举集合本质上不是线程安全的过程。即使在同步集合时,其他线程仍然可以修改集合,这会引发异常。只是性能说明-锁定操作非常昂贵,这就是为什么您应该执行双重检查以避免不必要的锁定:if(Contains…)lock(_mapLock)if(Contains…)Get…@Allon,1)lock并不像每个人想象的那样昂贵,但它也有成本。2) 您如何知道
包含
是线程安全的?如果在线程锁定集合时不调用它,则另一个线程可能会修改它(可能会执行内部调整大小),并且结果可能不可预测。我更喜欢始终锁定,除非相关对象的文档明确说明特定成员对于多个读卡器和一个写卡器是线程安全的(就像某些框架成员所做的那样)。Drew,由于.Contains()是只读操作(不修改共享状态),最糟糕的情况可能是它返回错误的结果(例如,它无法破坏共享状态)。如果返回错误的false,则不会执行此操作,并且不会发生任何不希望发生的情况。如果操作返回错误的true,则锁定对象,然后重新检查以防止此类误报。这是秒数检查的两个原因之一(另一个是为了防止竞争条件)。此外,锁非常昂贵——看看哪种锁实际上可以做一个简单的基准测试。在他的多线程测试中,使用锁的速度慢了17倍(13081毫秒对741毫秒)。我在这里没有发明轮子,引用-该模式旨在通过首先以不安全的方式测试锁定标准(“锁定提示”)来减少获取锁定的开销;只有成功,实际的锁定才会继续。"-注意“不安全”这个词。@Allon,锁没有那么贵。当然,锁是有成本的,但如果正确实现,则不会增加太多额外的处理时间。此外,软件是两种状态解决方案的一部分,另一种状态是硬件。硬件越大,任何锁定和并发问题都不会出现,除非软件写得不好10,在这种情况下,任何数量的分析器都会提前选择它,从而允许为n进行重新写入