3

I have a class (singleton) and it contains a static Dictionary

private static Dictionary<string, RepositoryServiceProvider> repositoryServices = null;

in the instance of this class I populate the dictionary (can occur from multiple threads). At first I had just

        RepositoryServiceProvider service = null; 
        repositoryServices.TryGetValue(this.Server.Name, out service);
        if (service == null) {
          service = new RepositoryServiceProvider(this.Server);
          repositoryServices.Add(this.Server.Name, service);  
        }

then I got some exceptions as Item already added so I changed it to:

        RepositoryServiceProvider service = null;    
        repositoryServices.TryGetValue(this.Server.Name, out service);
        if (service == null) {
          lock (padlock) {
            repositoryServices.TryGetValue(this.Server.Name, out service);
            if (service == null) {
              service = new RepositoryServiceProvider(this.Server);
              repositoryServices.Add(this.Server.Name, service);  
            }
          }
        }

and padlock is in the class:

private static readonly object padlock = new object();

is this thread safe? or its overcomplicated? or should I use ConcurentDictionary?

Zavael
  • 2,383
  • 1
  • 32
  • 44
  • 4
    Your changed code isn't thread-safe either: the initial `TryGetValue` needs to be inside the `lock` section too. But you'd be better off using something like [`ConcurrentDictionary`](http://msdn.microsoft.com/en-us/library/dd287191.aspx) instead, if possible, as suggested in [Yahia's answer](http://stackoverflow.com/a/9993904/55847) - it'll certainly be safer and less complicated, it might even be faster too. – LukeH Apr 03 '12 at 13:13
  • possible duplicate of http://stackoverflow.com/questions/9868219/dictionary-with-lock-or-concurency-dictionary/9868256#9868256 – daryal Apr 03 '12 at 13:14
  • @LukeH +1 for answer to my aproach thanks – Zavael Apr 03 '12 at 14:21

1 Answers1

8

IF you can use ConcurrentDictionary - it is in several situations faster than your approach because it implements most operations lock-free while being thread-safe.

EDIT - as per comments:

The term "most operations lock-free" is a bit too general...

Basically it means reduced contention ... thus in some cases more efficiency compared to a situation with one global lock, i.e. accessing a second bucket while the first bucket is locked works as if there was no lock from the POV of the accessing code... although that means a lock local to that bucket... in real-world applications it delivers much better performance than a global lock - esp. with multi-core.

Yahia
  • 69,653
  • 9
  • 115
  • 144
  • Do you have a reference for ConcurrentDictionary using lock-free operations? (I hope/think it doesn't). – H H Apr 03 '12 at 13:46
  • 3
    Lock-free thread-safe collections are the programmers' equivalent of a perpetuum mobile. "Can't see the lock" does not mean lock-free. – Hans Passant Apr 03 '12 at 13:47
  • As I wrote: most operations are lock-free due to how MS chose to implement them while still being thread-safe - see for example [here](http://geekswithblogs.net/BlackRabbitCoder/archive/2011/02/17/c.net-little-wonders-the-concurrentdictionary.aspx). It is definitely NOT completely lock-free as that couldn't be thread-safe... it locks internally as needed but it is carefully designed as to lock only when really really needed... – Yahia Apr 03 '12 at 13:56
  • 2
    @Yahia: As far as I know there's nothing lock-free about `CD`: most operations will need to lock, but it uses some kind of striping -- one lock per bucket, iirc -- to reduce contention. And, of course, some operations -- eg, resizing the internal array -- will still need to take out a global lock in order to keep everything safe. – LukeH Apr 03 '12 at 14:48
  • @LukeH IMO reduced contention means in some cases more efficiency compared to a situation with one global lock, i.e. accessing a second bucket while the first bucket is locked works as if there was no lock from the POV of the accessing code... – Yahia Apr 03 '12 at 14:57
  • @Yahia: I agree completely, that's why I upvoted your answer. I'm just nitpicking on the language used: less lock-contention isn't the same thing as lock-free. (And -- more nitpicking -- taking an uncontended lock does have a small cost. Not a cost that I'd be concerned about most of the time though.) – LukeH Apr 03 '12 at 15:08
  • @LukeH thanks - I expanded my answer to make that more clear. – Yahia Apr 03 '12 at 15:14