只允许管理视图
现在,我希望允许管理员列出字典中的所有值,但是管理员不会添加或删除条目,相反,我将提供一种方式让管理员通过遍历项来查看集合。
(伪)代码看起来类似于这个
foreach (var e in EmployeeCache.Instance.AllEmployees)
{
Console.WriteLine(e.Key);
}我的问题是:
如果我迭代这些项目,那么ConcurrentDictionary在读取时是否会被锁定?换句话说,ConcurrentDictionary是否被锁定,以便在管理代码只是迭代ConcurrentDictionary时,其他会话将无法添加或删除?
如果没有锁定,你能解释一下吗?
如果你认为它没有被锁定,你能简单总结一下它是如何做到的吗?例如,它是否为只读操作创建了ConcurrentDictionary的副本,然后允许运行读迭代--理解不会看到对真正字典的并发更改?
我想确定的是
我正在努力理解提供ConcurrentDictionary查看器的影响,管理员可以经常刷新它。也就是说,如果他们经常刷新它,它会影响网络应用程序的性能。当会话在等待对象解锁时,它们可以添加/删除项吗?
发布于 2014-06-16 15:38:07
ConcurrentDictionary.GetEnumerator是这样实现的:
/// <remarks>
/// The enumerator returned from the dictionary is safe to use concurrently with
/// reads and writes to the dictionary, however it does not represent a moment-in-time
/// snapshot of the dictionary. The contents exposed through the enumerator may contain
/// modifications made to the dictionary after <see cref="GetEnumerator"/> was called.
/// </remarks>
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
Node[] buckets = m_tables.m_buckets;
for (int i = 0; i < buckets.Length; i++)
{
// The Volatile.Read ensures that the load of the fields of 'current'
// doesn't move before the load from buckets[i].
Node current = Volatile.Read<Node>(ref buckets[i]);
while (current != null)
{
yield return new KeyValuePair<TKey, TValue>(current.m_key, current.m_value);
current = current.m_next;
}
}
}正如您所看到的,迭代是无锁的,只会产生一个不可变的结构(KeyValuePair),它将在每次迭代中返回给调用者。这就是为什么它不能保证ConcurrentDictionary的实时快照。
这肯定不会对迭代时添加/更新新值产生性能影响,但它只是不能保证管理员会看到字典中更新最多的快照。
发布于 2014-06-16 15:27:28
这就是文件的意思:
从字典返回的枚举器与读和写字典同时使用是安全的,但是它并不表示字典的即时快照。通过枚举器公开的内容可能包含调用GetEnumerator后对字典所做的修改。
http://msdn.microsoft.com/en-us/library/dd287131(v=vs.110).aspx
因此,如果您想要“快照”行为,您将必须创建一个Keys集合的副本并对该副本进行迭代,否则您将迭代可变线程安全集合。
https://stackoverflow.com/questions/24247029
复制相似问题