Fine-Grained Locking and Lock-Free Mechanisms

Some of the concurrent collection types use lightweight synchronization mechanisms such as SpinLockSpinWaitSemaphoreSlim, and CountdownEvent, which are new in the .NET Framework 4. These synchronization types typically use busy spinning for brief periods before they put the thread into a true Wait state. When wait times are expected to be very short, spinning is far less computationally expensive than waiting, which involves an expensive kernel transition. For collection classes that use spinning, this efficiency means that multiple threads can add and remove items at a very high rate. For more information about spinning vs. blocking, see SpinLock and SpinWait.

When to use a thread-safe collection

In env multi-threaded add and remove operations., To achieve thread-safety, these types use various kinds of efficient locking and lock-free synchronization mechanisms.

ConcurrentDictionary vs. Dictionary

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.

Also, although all methods of ConcurrentDictionary<TKey,TValue> are thread-safe, not all methods are atomic, specifically GetOrAdd and AddOrUpdate. To prevent unknown code from blocking all threads, the user delegate that’s passed to these methods is invoked outside of the dictionary’s internal lock.

ConcurrentDictionary Class

// So set the initial capacity to some prime number above that, to ensure that
// the ConcurrentDictionary does not need to be resized while initializing it.
int NUMITEMS = 64;
int initialCapacity = 101;

        // The higher the concurrencyLevel, the higher the theoretical number of operations
        // that could be performed concurrently on the ConcurrentDictionary.  However, global
        // operations like resizing the dictionary take longer as the concurrencyLevel rises.
        // For the purposes of this example, we'll compromise at numCores * 2.
        int numProcs = Environment.ProcessorCount;
        int concurrencyLevel = numProcs * 2;

        // Construct the dictionary with the desired concurrencyLevel and initialCapacity
        ConcurrentDictionary<int, int> cd = new ConcurrentDictionary<int, int>(concurrencyLevel, initialCapacity);

        // Initialize the dictionary
        for (int i = 0; i < NUMITEMS; i++) cd[i] = i * i;

        Console.WriteLine("The square of 23 is {0} (should be {1})", cd[23], 23 * 23);

Published by codeblogforfun

Coder, blogger, traveler

Leave a comment

Design a site like this with WordPress.com
Get started