Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET4.0: Thread-Safe Updating of ConcurrentDictionary<TKey, TValue>

Jumping off from this thread, I'm trying to use ConcurrentDictionary to replicate the following:

public static class Tracker
{
    private static Dictionary<string, int> foo = new Dictionary<string, int>();
    private static object myLock = new object();

    public static void Add(string bar)
    {
        lock(myLock)
        {
            if (!foo.ContainsKey(bar))
                foo.Add(bar, 0);

            foo[bar] = foo[bar] + 1;
        }
    }


    public static void Remove(string bar)
    {
        lock(myLock)
        {
            if (foo.ContainsKey(bar))
            {
                if (foo[bar] > 0)
                    foo[bar] = foo[bar] - 1;
            }
        }
    }
}

My initial attempt is:

public static class Tracker2
{
    private static ConcurrentDictionary<string, int> foo = 
        new ConcurrentDictionary<string, int>();

    public static void Add(string bar)
    {
        foo.AddOrUpdate(bar, 1, (key, n) => n + 1);
    }    

    public static void Remove(string bar)
    {
        // Adding a 0'd item may be ok if it wasn't there for some reason,
        //  but it's not identical to the above Remove() implementation.
        foo.AddOrUpdate(bar, 0, (key, n) => (n > 0) ? n - 1 : 0);
    }
}

Is this correct usage? Will I avoid situations such as:

  1. Thread 1: calls Add("a"), foo["a"] is now 1.
  2. Thread 1 is swapped out for Thread 2.
  3. Thread 2: calls Remove("a"), foo["a"] is now 0.
  4. Thread 2 is swapped out for Thread 1.
  5. Thread 1: Requests foo["a"] and assumes the value is 1 but it's actually 0.
like image 736
Bullines Avatar asked Nov 20 '10 19:11

Bullines


People also ask

Is ConcurrentDictionary values thread-safe?

Concurrent. ConcurrentDictionary<TKey,TValue>. This collection class is a thread-safe implementation.

Is ConcurrentDictionary clear thread-safe?

ConcurrentDictionary<TKey,TValue>. This collection class is a thread-safe implementation. We recommend that you use it whenever multiple threads might be attempting to access the elements concurrently.

Is ConcurrentDictionary Addorupdate thread-safe?

ConcurrentDictionary is thread-safe collection class to store key/value pairs. It internally uses locking to provide you a thread-safe class. It provides different methods as compared to Dictionary class. We can use TryAdd, TryUpdate, TryRemove, and TryGetValue to do CRUD operations on ConcurrentDictionary.

What is the purpose of the Concurrent Dictionary TKey TValue class?

Represents a thread-safe collection of key/value pairs that can be accessed by multiple threads concurrently.


1 Answers

You can't avoid the inconsistencies you are worried about just by using a ConcurrentDictionary. You need something much, much stronger and robust to guarantee that. Ask yourself if you really need that level of consistency before embarking on solving the problem. Dragons be there.

To repeat myself a little differently: ConcurrentDictionary only ensures multiple threads hitting the dictionary won't muck it up. It doesn't guarantee anything about consistency of the values when pulled successively by multiple threads. It can't keep you from shooting yourself in the foot.

like image 157
jason Avatar answered Sep 23 '22 00:09

jason