【问题标题】:C# .NET 4.0 ConcurrentDictionary: TryRemove within a lock?C# .NET 4.0 ConcurrentDictionary:在锁内尝试删除?
【发布时间】:2010-06-21 11:22:01
【问题描述】:

我相信这是可行的,我已经使用多个并发线程对其进行了测试(尽管对于竞争条件和死锁来说并不详尽):

public static System.Collections.Concurrent.ConcurrentDictionary<string, item> dict =
        new System.Collections.Concurrent.ConcurrentDictionary<string, item>();
public static item dump;

...

foreach (System.Collections.Generic.KeyValuePair<string, item> x in dict)
{
    lock (x.Value)
    {
        if (x.Value.IsCompleted)
        {
            dict.TryRemove(x.Key, out dump);
        }
    }
}

这个问题是这个问题的延续:

Can I remove items from a ConcurrentDictionary from within an enumeration loop of that dictionary?

还有这个问题:

Updating fields of values in a ConcurrentDictionary

我正在做两个“冒险”的动作:

  1. ConcurrentDictionary 中删除值,同时枚举它(这似乎没问题)。
  2. 锁定ConcurrentDictionaryValue 部分。必要,因为操作值的字段不是线程安全的,只有操作 ConcurrentDictionary 的值本身是线程安全的(上面的代码是一个更大的代码块的 sn-p,其中实际操作了值的字段)。

【问题讨论】:

    标签: c# multithreading .net-4.0 locking


    【解决方案1】:

    在迭代时从并发字典中删除值是可以的。它可能会对性能产生一些影响(我不确定),但它应该可以工作。

    请注意,您并没有锁定ConcurrentDictionary 的内部内容 - 您锁定的是与item 对象关联的监视器。我个人不想这样做:这些项目应该是线程安全的(无论如何都可以操作它们)或(最好)不可变的,这样您就可以从任何线程观察它们而无需锁定。当然,或者您可以只使您正在检查的单个属性成为线程安全的。记录你所做的一切!

    最后,您对out dump 的使用似乎有点可疑。重要的是要给TryRemove一些东西吗?如果是这样,我会使用局部变量而不是静态变量。

    【讨论】:

    • 感谢乔恩,是的:转储意味着毫无意义的笼统。我将把它变成一个局部变量,因为全局范围公共静态是项目中的属性的一个漏洞:我将锁定单个属性而不是项目,正如你所建议的。可能有一种更优雅的方式来处理这个问题,但是这些属性将在一个线程中更改,在另一个线程中读取,并在第三次欢呼中在项目级别删除!
    【解决方案2】:

    我最近发现的一个很好的替代方法是仅当键/值匹配时才删除,这意味着您可以保证删除一个没有变化的对象(最好是值类型,而不是引用类型) .示例:

     ConcurrentDictionary<string, int> cc = new ConcurrentDictionary<string, int>();
    
            cc.GetOrAdd("1", 1);
    

    现在假设下面两行运行在并发/多线程场景中。

            cc.AddOrUpdate("1", 2, (a,b) => b + 1);
    
             var removeSuccess = ((ICollection<KeyValuePair<string, int>>)cc).Remove(
        new KeyValuePair<string, int>("1", 1));
    

    如果值没有改变,您将成功删除“1”,否则将失败,因为您已经为同一个键设置了新值。

    欲了解更多信息,请查看以下内容: http://thargy.com/2012/09/the-hidden-secret-of-the-concurrent-dictionary/http://blogs.msdn.com/b/pfxteam/archive/2011/04/02/10149222.aspx

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-29
      • 2020-04-18
      • 1970-01-01
      • 1970-01-01
      • 2011-04-23
      • 1970-01-01
      • 2012-10-07
      相关资源
      最近更新 更多