rad*_*vus 12 c# collections session multithreading dictionary
仅允许管理员查看
现在,我想允许管理员列出字典中的所有值,但是管理员不会添加或删除项目,而是我只会通过迭代通过读取集合来为管理员提供查看项目的方法这几项.
(伪)代码看起来像这样:
foreach (var e in EmployeeCache.Instance.AllEmployees)
{
Console.WriteLine(e.Key);
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:
如果我遍历项目,ConcurrentDictionary在被读取时会被锁定吗?换句话说,ConcurrentDictionary是否被锁定,以便在管理代码只是通过ConcurrentDictionary迭代时,其他会话将无法添加或删除?
如果没有锁定,你能解释一下吗?
如果您认为它没有锁定,您能否快速总结一下它是如何做到的?例如,它是否为只读操作创建ConcurrentDictionary的副本,然后允许读取迭代运行 - 了解不会看到对真实字典的并发更改?
我想要确定的是什么
我试图了解提供ConcurrentDictionary查看器的影响,该查看器可以由管理员经常刷新.IE如果他们经常刷新它可能会影响Web应用程序的性能.会话正在等待对象解锁,以便他们可以添加/删除项目?
Yuv*_*kov 10
这是如何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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,迭代是无锁的,只是产生一个不可变的struct(KeyValuePair),它会在每次迭代时返回给调用者.这就是为什么它无法保证时间的快照ConcurrentDictionary
在迭代时,这肯定不会对添加/更新新值产生性能影响,但它无法保证您的管理员将看到字典的最新快照.
这就是文档所说的:
从字典返回的枚举数可以安全地与对字典的读取和写入同时使用,但是它不代表字典的即时快照。通过枚举器公开的内容可能包含在调用GetEnumerator之后对字典所做的修改。
http://msdn.microsoft.com/zh-CN/library/dd287131(v=vs.110).aspx
因此,如果您想要“快照”行为,则必须制作Keys集合的副本并在该副本上进行迭代,否则,将在可变线程安全集合上进行迭代。