简体   繁体   English

ThreadSafe 字典...键值对可枚举? (。网)

[英]ThreadSafe Dictionary… Key Value Pairs Enumerable? (.net)

I'm perusing (considering writing my own thread safe dictionary) I found the following implementation.我正在阅读(考虑编写我自己的线程安全字典)我发现了以下实现。

http://devplanet.com/blogs/brianr/archive/2008/09/26/thread-safe-dictionary-in-net.aspx http://devplanet.com/blogs/brianr/archive/2008/09/26/thread-safe-dictionary-in-net.aspx

It looks pretty good generally, but there's one thing that confuses me.总的来说,它看起来不错,但有一件事让我感到困惑。

The following: Cannot enumerate a threadsafe dictionary.以下内容: 无法枚举线程安全字典。 Instead, enumerate the keys or values collection相反,枚举键或值集合

which is found in both the在这两个中都可以找到

public virtual IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
    throw new NotSupportedException("Cannot enumerate a threadsafe dictionary.  Instead, enumerate the keys or values collection");
}


IEnumerator IEnumerable.GetEnumerator()
{
    throw new NotSupportedException("Cannot enumerate a threadsafe dictionary.  Instead, enumerate the keys or values collection");
}

What I don't get is why it's ok to enumerate the keys or values, but not the kvp's of the dictionary?我不明白为什么可以枚举键或值,而不是字典的kvp?

Could someone shed some light on this for me?有人可以为我解释一下吗? Thanks in advance.提前致谢。

SO user and MS employee JaredPar has a short series on his blog about building threadsafe collections that's definitely worth your time: SO 用户和 MS 员工JaredPar在他的博客上有一个关于构建线程安全 collections 的简短系列,绝对值得您花时间:

[Update:] [更新:]
Reading through them again, if you're short of time the 2nd article can probably stand on it's own.再次阅读它们,如果您时间不够,第二篇文章可能会独立存在。

To summarize: most "threadsafe" collections you find posted online are generally either not very useful or only thread safe one operation at a time, making "decision" members like .Count or .Contains useless (they're "stale" by the time the next line of code runs).总而言之:您发现在线发布的大多数“线程安全” collections 通常不是很有用,或者一次只有一个线程安全操作,使得 .Count 或.Count .Contains类的“决策”成员无用(到时候它们已经“陈旧”了)下一行代码运行)。

I can answer that question directly, since I wrote that dictionary:)我可以直接回答这个问题,因为我写了那本字典:)

Obtaining an enumerator on the dictionary will get a reference to the internal KVP sets.获取字典上的枚举器将获得对内部 KVP 集的引用。 You would have to hold the read lock until you are done enumerating, which could be a long while.在完成枚举之前,您必须持有读锁,这可能需要很长时间。

The reason I say to enumerate the keys or values instead, is that I copy the list of keys and values when it is requested, therefore I am not returning a reference to the dictionaries internal list, which if you altered out of lock, could cause issues.我说要枚举键或值的原因是,我在请求时复制了键和值的列表,因此我没有返回对字典内部列表的引用,如果您更改失锁,可能会导致问题。 Although, I suppose you could implement the same pattern on the KVP's as well if you wanted since they are read only.虽然,我想如果你愿意,你也可以在 KVP 上实现相同的模式,因为它们是只读的。

    public virtual ICollection<TKey> Keys
    {
        get
        {
            using (new ReadOnlyLock(this.dictionaryLock))
            {
                return new List<TKey>(this.dict.Keys);
            }
        }
    }

    public virtual ICollection<TValue> Values
    {
        get
        {
            using (new ReadOnlyLock(this.dictionaryLock))
            {
                return new List<TValue>(this.dict.Values);
            }
        }
    }

When you enumerate over the collection of KVP you are dipping into and out of the lock for the entire dictionary.当您枚举 KVP 的集合时,您将进入和退出整个字典的锁定。 So in the loop body of your enumeration you are not in the lock, and changing the KVP could cause a race condition.因此,在您的枚举的循环体中,您并未处于锁定状态,更改 KVP 可能会导致竞争条件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM