Thread safe data lookups with ConcurrentDictionary

ConcurrentDictionary is the thread safe counterpart to the generic dictionary collection. Both are designed for quick lookups of data based on a key. However, ConcurrentDictionary allows us to interleave both reads and updates. ConcurrentDictionary achieves its thread safety with no common lock to improve efficiency. It actually uses a series of locks to provide concurrent updates, and has lockless reads.

In this recipe, we will create ConcurrentDictionary and initialize it with a small set of key value pairs. Our dictionary will be concurrently updated by one task and read by another.

How to do it…

Let's take a look at how to use ConcurrentDictionary for data lookups.

  1. Start a new project using the C# Console Application project template and assign ConcurrentDictionary as the Solution name.
  2. Add the following using directives to the top of your Program class:
    using System;
    using System.Collections.Concurrent;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
  3. First, let's create our ConcurrentDictionary and initialize it with some data.
    var dictionary = new ConcurrentDictionary<string, int>();
    dictionary["A"] = 1;
    dictionary["B"] = 2;
    dictionary["C"] = 3;
    dictionary["D"] = 4;
    dictionary["E"] = 5;
    dictionary["F"] = 6;
    dictionary["G"] = 7;
    dictionary["H"] = 8;
    dictionary["I"] = 9;
    dictionary["J"] = 10;
    dictionary["K"] = 11;
    dictionary["L"] = 12;
    dictionary["M"] = 13;
    dictionary["N"] = 14;
    dictionary["O"] = 15;
  4. Now let's create Task to update dictionary on a separate thread.
    // update dictionary on a separate thread
    Task.Factory.StartNew(() =>
    {
        foreach (var pair in dictionary)
        {
            var newValue = pair.Value + 1;
            dictionary.TryUpdate(pair.Key,newValue,pair.Value);
            Console.WriteLine("Updated key: {0} value:{1}", pair.Key, newValue);
        }   
    });
  5. Now let's create another Task which will be concurrently reading from dictionary.
    Task.Factory.StartNew(() =>
    {
        foreach (var pair in dictionary)
        {
            Console.WriteLine("Reading key: {0} value:{1}",pair.Key,pair.Value);
        }
    });            
    
    Console.ReadLine();
  6. In Visual Studio 2012, press F5 to run the project. You should see the output as shown in the following screenshot:
    How to do it…

How it works…

ConcurrentDictionary behaves like dictionary counterpart with slight differences. We are updating dictionary using the TryUpdate method. This method was added to provide us with an atomic operation to check if the item exists, and if not, add it while still under an atomic lock.

foreach (var pair in dictionary)
    {
        var newValue = pair.Value + 1;
        dictionary.TryUpdate(pair.Key,newValue,pair.Value);
        Console.WriteLine("Updated key: {0} value:{1}", pair.Key, newValue);
    }

We are reading dictionary directly from the Key and Value properties of each KeyValuePair in the collection.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.17.203.68