【问题标题】:Is Keys collection in ConcurrentDictionary is thread safe [duplicate]ConcurrentDictionary 中的 Keys 集合是线程安全的吗?
【发布时间】:2017-12-28 06:12:34
【问题描述】:

我必须通过某些键从 ConcurrentDictionary 中删除项目。像这样:

ConcurrentDictionary<SomeClass, string> dict = new ConcurrentDictionary<SomeClass, string>();
//adding some values
var keys = dict.Keys.Where(k => k.Name == "Example");
foreach (var key in keys)
    dict.TryRemove(key, out _);

问题是:我在开始循环时枚举键集合。如果有人同时更改字典怎么办? dict.Keys 是否返回快照?

【问题讨论】:

  • 它返回一个副本。见here
  • 它返回一个snapshot(所以是的,它会正常工作)。我建议使用var keys = dict.Select(z =&gt; z.Key).Where(k =&gt; k.Name == "Example"); 来减少对快照的需求(即锁定)——即它通常会更快。或者只是在字典上foreach,就像在副本中一样。

标签: c# concurrency


【解决方案1】:

source code

public ICollection<TKey> Keys
{
    get { return GetKeys(); }
}

private ReadOnlyCollection<TKey> GetKeys()
{
    int locksAcquired = 0;
    try
    {
        AcquireAllLocks(ref locksAcquired);

        int count = GetCountInternal();
        if (count < 0) throw new OutOfMemoryException();

        List<TKey> keys = new List<TKey>(count);
        for (int i = 0; i < _tables._buckets.Length; i++)
        {
            Node current = _tables._buckets[i];
            while (current != null)
            {
                keys.Add(current._key);
                current = current._next;
            }
        }

        return new ReadOnlyCollection<TKey>(keys);
    }
    finally
    {
        ReleaseLocks(0, locksAcquired);
    }
}

它锁定集合并返回密钥副本

【讨论】:

    【解决方案2】:

    ConcurrentDictionary 的所有公共和受保护成员 是线程安全的,可以从多个线程同时使用。 但是,通过其中一个接口访问的成员 ConcurrentDictionary 实现,包括扩展 方法,不保证是线程安全的,可能需要 由调用者同步。

    来自https://msdn.microsoft.com/en-us/library/dd287191(v=vs.110).aspx#Anchor_10

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多