Search code examples
c#multithreadingthread-safetyimmutabilitybase-class-library

Using Bcl ImmutableDictionary in private field


Let's say I have a class that will be called from multiple threads, and am going to store some data in an ImmutableDictionary in a private field in this class

public class Something {
    private ImmutableDictionary<string,string> _dict;
    public Something() {
       _dict = ImmutableDictionary<string,string>.Empty;
    }

    public void Add(string key, string value) {

       if(!_dict.ContainsKey(key)) {
          _dict = _dict.Add(key,value);
       }
    }
}

Could this be called in such a way by multiple threads that you will get an error about the key already existing in the dictionary?

Thread1 checks dictionary sees false Thread2 checks dictionary sees false Thread1 adds value and reference to _dict is updated Thread2 adds value, but it is already added because it uses the same reference?


Solution

  • Yes, just the same race as usual applies (both threads read, find nothing, then both threads write). Thread-safety is not a property of a data-structure but of an entire system.

    There is another problem: Concurrent writes to different keys will just lose writes.

    What you need is a ConcurrentDictionary. You cannot make this work with the immutable one without an additional lock or a CAS-loop.

    Update: The comments convinced me that an ImmutableDictionary used with a CAS-loop for writes is actually a very good idea if writes are infrequent. Read performance will be very nice and writes as cheap as it gets with a synchronized data structure.