【问题标题】:Is the ConcurrentDictionary thread-safe to the point that I can use it for a static cache?ConcurrentDictionary 线程安全到我可以将它用于静态缓存的程度吗?
【发布时间】:2011-10-08 00:38:12
【问题描述】:

基本上,如果我想做以下事情:

public class SomeClass
{
    private static ConcurrentDictionary<..., ...> Cache { get; set; }
}

这是否让我避免到处使用locks?

【问题讨论】:

    标签: c# locking static-members concurrent-collections


    【解决方案1】:

    是的,它是线程安全的,是的,它可以避免你到处使用锁(不管这意味着什么)。当然,这只会为您提供对该字典中存储的数据的线程安全访问,但如果数据本身不是线程安全的,那么您当然需要同步访问它。例如,假设您在此缓存中存储了List&lt;T&gt;。现在 thread1 获取此列表(以线程安全的方式,因为并发字典向您保证这一点),然后开始枚举此列表。在同一时间,thread2 从缓存中获取这个相同的列表(以线程安全的方式,因为并发字典向您保证这一点)并写入列表(例如,它添加一个值)。结论:如果你没有同步thread1,它会遇到麻烦。

    就将其用作缓存而言,这可能不是一个好主意。对于缓存,我会向您推荐框架中已经内置的内容。例如MemoryCache 之类的类。这样做的原因是,System.Runtime.Caching 程序集中内置的内容是为缓存而明确构建的 => 如果您开始内存不足,它会处理数据自动过期,缓存过期项目的回调,您会甚至可以使用 memcached、AppFabric 之类的东西将缓存分布在多个服务器上,...,所有这些都是您使用并发字典无法想象的。

    【讨论】:

    • MemoryCache 类是否像 ConcurrentDictionary 一样是线程安全的?
    • @michael,是的,它是线程安全的,但是关于同步访问您可能存储到此缓存中的非线程安全对象,这句话绝对是正确的。
    • 哦,那部分我明白了。但是,为了让其他读者能够理解,我将重申它。您是说ConcurrentDictionaryMemoryCache 类都是线程安全的,但不能保证其中的内容是线程安全的。 :)
    • @michael,准确地说,很好。我的英语太差了,我无法表达自己。
    【解决方案2】:

    您可能仍然需要使用锁定,就像您可能需要数据库中的事务一样。 “并发”部分意味着字典将继续在多个线程中正确运行。

    并发集合中内置了 TryGetValue 和 TryRemove,它们承认有人可能会先删除一个项目。粒度级别的锁定是内置的,但您仍然需要考虑在这些情况下该怎么做。对于缓存,它通常并不重要——即它是一个幂等操作。

    re:缓存。我感觉这取决于您在缓存中存储的内容+您正在使用它做什么。有与使用对象相关的铸造成本。可能对于大多数基于 Web 的事物,MemCache 更适合上面的建议。

    【讨论】:

      猜你喜欢
      • 2013-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-25
      • 2010-11-08
      • 1970-01-01
      • 2021-09-20
      相关资源
      最近更新 更多