ConcurrentQueue
has TryDequeue
method.
Queue
has just Dequeue
method.
In ConcurrentDictionary
there is no Add
method, but we have TryAdd
instead.
My question is:
What is the diffrence between these concurrent collection methods? Why they are diffrent for concurrent collections?
With a Dictionary<TKey, TValue>
it's assumed that you're going to implement your own logic to make sure duplicate keys aren't entered. For example,
if(!myDictionary.ContainsKey(key)) myDictionary.Add(key, value);
But we use Concurrent collections when we have multiple threads going and it's possible that they could both be trying to modify the dictionary at the same time.
If two threads tried to execute the above code at the same time, it's possible that myDictionary.ContainsKey(key)
could return false for both threads because they're both checking at the same time and that key hasn't been added yet. Then they both try to add the key, and one fails.
Someone reading that code who doesn't know it's multithreaded could be confused. I checked to make sure that the key wasn't in the dictionary before I added it. So how am I getting an exception?
ConcurrentDictionary.TryAdd
solves that by allowing you to "try" to add the key. If it adds the value it returns true
. If it doesn't it returns false
. But what it won't do is conflict with another TryAdd
and throw an exception.
You could do all of that yourself by wrapping the Dictionary
in a class and putting lock
statements around it to make sure only one thread at a time makes changes. ConcurrentDictionary
just does that for you and does it really well. You don't have to see all the details of how it's working - you just use it knowing that multithreading has been accounted for.
Here's a detail to look for when using a class in a multithreaded application. If you go to the documentation for ConcurrentDictionary Class and scroll to the bottom you'll see this:
Thread Safety
All public and protected members of ConcurrentDictionary are thread-safe and may be used concurrently from multiple threads. However, members accessed through one of the interfaces the ConcurrentDictionary implements, including extension methods, are not guaranteed to be thread safe and may need to be synchronized by the caller.
In other words, multiple threads can safely read and modify the collection.
Under Dictionary Class you'll see this:
Thread Safety
A Dictionary can support multiple readers concurrently, as long as the collection is not modified. Even so, enumerating through a collection is intrinsically not a thread-safe procedure. In the rare case where an enumeration contends with write accesses, the collection must be locked during the entire enumeration. To allow the collection to be accessed by multiple threads for reading and writing, you must implement your own synchronization.
Multiple threads can read keys, but if multiple threads are going to write then you need to somehow lock
the dictionary to make sure only one thread at a time tries to update.
Dictionary<TKey, TValue>
exposes a Keys
collection and Values
collection so you can enumerate the keys and values, but it warns you not to try doing that if another thread is going to be modifying the dictionary. You can't enumerate something while items are being added or removed. If you need to iterate through the keys or values then you have to lock the dictionary to prevent updates during that iteration.
ConcurrentDictionary<TKey, TValue>
assumes that there will be multiple threads reading and writing, so it doesn't even expose key or value collections for you to enumerate.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With