Is it OK to use Dictionary instead of ConcurrentDictionary in multithreading program when the number of keys is fixed?

Viewed 126

I know in multithreading program, we need to use ConcurrentDictionary, ConcurrentBag etc those thread-safe collection. But in my situation, the number of keys in Dictionary is fixed, I have exact 5 keys which I already know before the program executes so I can initialize the dictionary's key. So my thinking is, because the number of the keys is not going to change, I can actually use Dictionary instead of ConcurrentDictionary, and the reason I am thinking to do this, is because the collection won't resize internally, so there won't be a situation when thread1 try to update an element after thread2 adds a new element then cause resizing, which makes thread1's update fail. Is my understanding correct?

More information:

I don't have a shared key/value pair that can be updated by all threads, each thread just update a particular key/value pair and TKey is a unique string, TValue is simple class type

2 Answers

The documentation of the Dictionary<TKey, TValue> class states explicitly that:

To allow the collection to be accessed by multiple threads for reading and writing, you must implement your own synchronization.

So, based on the documentation, if you modify the dictionary by multiple threads without synchronization, you have entered the "undefined behavior" territory. Meaning that "anything" can happen, and whatever happens will not be a bug. The warranty has been breached, and Microsoft couldn't care less about any damages that have occurred to you, after using their products incorrectly.

That said, and knowing how the Dictionary<TKey, TValue> class is implemented, it's unlikely that you'll have any issues by using a Dictionary<TKey, TValue> in a lock-free manner, if you follow the very strict usage pattern that you describe in your question. It's up to you decide if it's OK to rely on implementation details of the API that you use, instead of the published documentation.

As a side note, be aware that in general searching serially for a value in a small List<T> or array outperforms searching for a value in a small hash-based Dictionary<TKey, TValue>. The tipping point depends on the type of the key, and might be as large as 50 elements or more. Also for storing one value per thread, you might find the ThreadLocal<T> class useful.

Summary

  1. It will work.
  2. Relying on current implemenation is considered bad practice. Avoid it if you can.
  3. Optimising early is considered bad practice. Use a safest option and reassess only if confirmed too slow.
  4. A shared dictionary seem like a interesting choice here: it doesn't seem to add any functionality to your solution. A different solution (e.g. 5 variables) would work better here.

I really want it. Can I? Yes, but.

If

  1. the dictionary keys never change and
  2. only one thread accesses value for a given key

then locking in the current implementation is not needed (i.e. Dictionary is fine) because the dictionary itself doesn't change and a single consumer accesses each value.

Is it OK? Not really

Generally, it is not OK to use code which works but uses structures that have better alternatives for a given scenario. Code like this is very easy to break without knowing until it is deployed in a real life scenario and even then it's hard to find out the issue quickly.

Related