Is the ConcurrentDictionary thread-safe to the point that I can use it for a static cache?
Asked Answered
R

2

26

Basically, if I want to do the following:

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

Does this let me avoid using locks all over the place?

Ringhals answered 18/7, 2011 at 20:43 Comment(0)
T
40

Yes, it is thread safe and yes it avoids you using locks all over the place (whatever that means). Of course that will only provide you a thread safe access to the data stored in this dictionary, but if the data itself is not thread safe then you need to synchronize access to it of course. Imagine for example that you have stored in this cache a List<T>. Now thread1 fetches this list (in a thread safe manner as the concurrent dictionary guarantees you this) and then starts enumerating over this list. At exactly the same time thread2 fetches this very same list from the cache (in a thread safe manner as the concurrent dictionary guarantees you this) and writes to the list (for example it adds a value). Conclusion: if you haven't synchronized thread1 it will get into trouble.

As far as using it as a cache is concerned, well, that's probably not a good idea. For caching I would recommend you what is already built into the framework. Classes such as MemoryCache for example. The reason for this is that what is built into the System.Runtime.Caching assembly is, well, explicitly built for caching => it handles things like automatic expiration of data if you start running low on memory, callbacks for cache expiration items, and you would even be able to distribute your cache over multiple servers using things like memcached, AppFabric, ..., all things that you would can't dream of with a concurrent dictionary.

Teetotal answered 18/7, 2011 at 20:45 Comment(4)
Is the MemoryCache class thread-safe like the ConcurrentDictionary is though?Ringhals
@michael, yes it is thread safe but absolutely the same remark stands true about synchronizing access to non thread-safe objects that you might be storing into this cache.Teetotal
Oh, I understand that part. But, just so that other readers can understand I'm going to reiterate it. You're saying that both the ConcurrentDictionary and MemoryCache class are thread-safe, but the contents within are not guaranteed to be thread-safe. :)Ringhals
@michael, exactly, nicely put. My English is so poor that I can't express myself.Teetotal
N
3

You still may need to use locking in the same way that you might need a transaction in a database. The "concurrent" part means that the dictionary will continue to function correctly across multiple threads.

Built into the concurrent collection are TryGetValue and TryRemove which acknowledge that someone might delete an item first. Locking at a granular level is built in, but you still need to think about what to do in these situations. For Caching, it often doesn't matter -- i.e. it's an idempotent operation.

re: caching. I feel that it depends on what you are storing in the cache + what you are doing with it. There are casting costs associated with using an object. Probably for most web based things MemCache is better suited as suggested above.

Nodababus answered 18/7, 2011 at 20:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.