Concurrent Dictionary is a new member of Collection family since.Net 4.0 and this Dictionary will be used to handle multiple threads scenarios. Let’s dig more into this collection.

ConcurrentDictionary can be found in System.Collections.Concurrent namespace.

If you are working with multiple threads and want to access or add an item to the Dictionary in parallel then your results might get wrong because the default Dictionary is not thread-safe so there could be a chance to add an item which already added by another thread running in parallel. Let’s take simple example below

class Program
{
    static Dictionary<string, int> _mydictionary = new Dictionary<string, int>();

    static void Main()
    {
        Thread mythread1 = new Thread(new ThreadStart(InsertData));
        Thread mythread2 = new Thread(new ThreadStart(InsertData));
        mythread1.Start();
        mythread2.Start();
        mythread1.Join();
        mythread2.Join();
        Console.WriteLine($"Result in Average: {_mydictionary.Values.Average()}");
    }

    static void InsertData()
    {
        for (int i = 0; i < 100; i++)
        {
            _mydictionary.Add(System.Guid.NewGuid(), i);
        }
    }
}

 

Can you guess the result?? Do you think this will return the expected results every time?? No, why because here two threads are parallelly accessing this dictionary and there might be a chance to add the duplicate value of the same number. To solve this problem this dictionary should be thread-safe and shouldn’t allow accessing by another thread until this thread completes its action i.e.., it should execute concurrently. To achieve this functionality a new collection called ConcurrentDictonary was introduced in .Net framework 4.0.

The same simple example as above will implement using ConcurrentDictonary

class Program
{
    static ConcurrentDictionary<string, int> _mydictionary = new ConcurrentDictionary<string, int>();

    static void Main()
    {
        Thread mythread1 = new Thread(new ThreadStart(InsertData));
        Thread mythread2 = new Thread(new ThreadStart(InsertData));
        mythread1.Start();
        mythread2.Start();
        mythread1.Join();
        mythread2.Join();
        Console.WriteLine($"Result in Average: {_mydictionary.Values.Average()}");
    }

    static void InsertData()
    {
        for (int i = 0; i < 100; i++)
        {
            _mydictionary.TryAdd(System.Guid.NewGuid(), i);
        }
    }
}

As observed, there is no much change in implementation except

  1. _mydictionaty is now ConcurrentDictionary object
  2.  Instead of calling Add() method now we are calling TryAdd().

Following are the core methods need to know of ConcurrentDictionary class

  • TryAdd() – This is same as Add() method in Dictionary class but it won’t throw any exception when there is already an item exists with the same key, in this case, it will return false.
  • TryGetValue() – This will try to get the value of given key, if not exist it will return null.
  • TryRemove() – This Remove is somewhat different from regular Remove() method in Dictionary class, as here when we say TryRemove it will contain another out parameter where it will set the removed item.
  • TryUpdate() – This method gives some extra functionality like we can provide some value there along with value to be updated and the system will validate whether given value is equal to the existing value, if not the update will be failed.
  • AddOrUpdate() – This is a special method where it will contain 3 parameters (Key, value, value-to-update), if system found given key then it will be updated by value-to-update and if this key not found it will be added as a new key with value value parameter.
  • GetOrAdd() – This is similar to AddOrUpdate() but it won’t update any key, it take 2 parameters (key, value), if system found the key then it will return the value in the Dictionary and omits the given value parameter. If the key doesn’t exist a new item with this given key and value will be added to the Dictionary.

Final Note:

  • ConcurrentDictionary<TKey, TValue> is designed for multithreaded scenarios. You do not have to use locks in your code to add or remove items from the collection. However, it is always possible for one thread to retrieve a value, and another thread to immediately update the collection by giving the same key a new value.
  • Although all methods of ConcurrentDictionary<TKey, TValue> are thread-safe, not all methods are atomic, specifically GetOrAdd and AddOrUpdate. The user delegate that is passed to these methods is invoked outside of the dictionary’s internal lock.

Performance:
Coming to performance comparison between Dictionary and ConcurrentDictionary, Dictionary will give us almost 30% more efficient than ConcurrentDictionary while adding or retrieving. Use ConcurrentDictionary only in case of multi-threaded scenarios.

 

Hope this Helpful a lot..

Happy Coding 🙂