C# 为并发字典公开GetEnumerator()
我正在为C#开发一个并发字典实现,我想知道这个C# 为并发字典公开GetEnumerator(),c#,multithreading,C#,Multithreading,我正在为C#开发一个并发字典实现,我想知道这个GetEnumerator()implementation是否真的(线程)安全 它没有执行实际的快照,所以我想知道它是否会在以后读/写内部字典时出错,或者它是否会暴露潜在的死锁,因为公开的IEnumerator的枚举实际上会在锁内运行 private readonly Dictionary<TKey, TValue> internalDictionary; private SpinLock spinLock = new SpinLock(
GetEnumerator()
implementation是否真的(线程)安全
它没有执行实际的快照,所以我想知道它是否会在以后读/写内部字典时出错,或者它是否会暴露潜在的死锁,因为公开的IEnumerator
的枚举实际上会在锁内运行
private readonly Dictionary<TKey, TValue> internalDictionary;
private SpinLock spinLock = new SpinLock();
IEnumerator IEnumerable.GetEnumerator()
{
IEnumerator enumerator;
bool lockTaken = false;
try
{
spinLock.TryEnter(ref lockTaken);
enumerator = (this.internalDictionary as IEnumerable).GetEnumerator();
}
finally
{
if (lockTaken)
{
spinLock.Exit(false);
}
}
return enumerator;
}
专用只读词典;
私有自旋锁自旋锁=新自旋锁();
IEnumerator IEnumerable.GetEnumerator()
{
IEnumerator枚举器;
bool-locktake=false;
尝试
{
自旋锁。TryEnter(参考锁定);
枚举数=(this.internalDictionary为IEnumerable).GetEnumerator();
}
最后
{
如果(已锁定)
{
spinLock.Exit(false);
}
}
返回枚举器;
}
首先想到的是,当.NET附带线程安全的并发集合类(包括字典)时,您究竟为什么要自己创建这样一个beast。谷歌System.Collections.Concurrent
获取更多信息
我之前已经对ConcurrentDictionary类进行了基准测试,我可以向您保证,它们比您自己编写的任何东西都要快得多,即使在使用自旋锁或互锁以避免任何更重的锁定机制时也是如此
在回答您的问题时,可能,但这取决于实施情况(这从来都不是一件好事)。我猜任何写入尝试都会失败,因为标准集合类在迭代时无法修改;但是我不会依赖任何这样的机制来保证我自己的代码的安全。对于并发编写器,您的方法不是线程安全的,因为
ToList
,或者调用其他东西来实际快照IEnumerator IEnumerable.GetEnumerator()
{
lock (internalDictionary) return internalDictionary.ToList();
}
同时写作的人也必须掌握这把锁。“snapsnot”我希望这是一个打字错误……是的,但他们明确建议你不要编辑一个字母的打字错误。这里没有具体问题……用粗体突出了实际问题。问题是这个实现是否是线程安全的。显而易见的答案是,ConcurrentDictionary并不是在所有的.NET平台上都受支持。至于答案,这是一个完全不公开枚举器的合理理由,而只是通过提供快照。常规键/值属性。@Claus确实是。我建议研究ConcurrentDictionary的API表面,即使您无法使用实现,因为我相信MS也考虑过同样的问题。也许你可以用C5?它是一个非常全面且线程安全的数据结构(集合、树等)库。有关详细信息,请参阅。@ClausJørgensen默认情况下C5集合也不是线程安全的。相反,我可以为您提供一个使用Interlocked的线程安全字典的实现,这是我为Fasterflect库编写的。代码可在(向下滚动至#elif DOT_NET_35行)找到。它可能没有你所需要的一切,但提供了一个体面的起点。而且,它使用联锁,因此速度相当快。是的,但这确实会返回快照;)至于3号和4号,这实际上已经被锁上了。不知道你在说什么。调用GetEnumerator不会快照字典的内容。是的,这就是我的观点。我在问题中提到,我知道它没有拍摄快照。因此,让我更恰当地回答您的问题:由于您没有拍摄快照,并且在读取枚举器时没有锁定,因此您不是线程安全的,并且正在破坏字典的内部状态。即使锁被使用,枚举数也会在第一次写入时失效(它将停止工作)。这有帮助吗?这就是我想要得到证实的,是的。