ConcurrentDictionary是否是线程安全的,我可以将它用于静态缓存?

时间:2011-07-18 20:43:37

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

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

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

这是否让我避免在整个地方使用lock

2 个答案:

答案 0 :(得分:31)

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

就使用它作为缓存而言,这可能不是一个好主意。对于缓存,我会向您推荐已构建到框架中的内容。例如MemoryCache等类。这样做的原因是System.Runtime.Caching程序集中内置的内容是为缓存明确构建的=&gt;如果你开始运行低内存,缓存过期项目的回调,你甚至可以使用memcached,AppFabric,...等所有东西在多个服务器上分配你的缓存,它会处理数据的自动过期等事情。无法用并发字典做梦。

答案 1 :(得分:3)

您仍可能需要以与数据库中可能需要事务相同的方式使用锁定。 “并发”部分意味着字典将继续在多个线程中正常运行。

并发集合中包含TryGetValue和TryRemove,它们确认某人可能先删除某个项目。内置锁定在粒度级别,但您仍需要考虑在这些情况下要执行的操作。对于缓存,它通常无关紧要 - 即它是幂等操作。

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