Double-Check Lock in .NET.

+52
multithreading double-checked-locking paradigms
Dec 27 '08 at 11:05
source share
8 answers

The implementation of the Singleton template in C # talks about this problem in the third version.

It says:

Creating an instance variable volatile can make it work, as well as explicit calls to the memory barrier, although in the latter case, even experts cannot agree on what kind of barriers are needed. I try to avoid situations when experts disagree on what is right and what is not!

The author seems to imply that double locking is less likely to work than other strategies, and therefore should not be used.

+25
Dec 27 '08 at 11:21
source share

Double locking check now works in both Java and C # (the Java memory model has changed, and this is one of the effects). However, you must get it right. If you mess things up a bit, you can completely lose the thread's security.

As pointed out in other answers, if you are using a singleton pattern , there are much better ways to do this. Personally, if I am in a situation where I have to choose between a double-checked lock and the "block every time" code, I would go to the lock each time until I got real evidence that this causes a bottleneck. When it comes to threads, a simple and clearly correct template costs a lot.

+72
Dec 27 '08 at 11:47
source share

.NET 4.0 has a new type: Lazy<T> , which fixes any problem with incorrect display of a template. This is part of the new parallel task library.

See the MSDN Parallel Computing Developer Center: http://msdn.microsoft.com/en-us/concurrency/default.aspx

By the way, there is a backport (I believe that it is not supported) for .NET 3.5 SP1 is available here .

+24
May 25 '10 at 23:46
source share

Note that in Java (and most likely in .Net too), a double lock check to initialize a singleton is completely unnecessary and also does not work. Since classes are not initialized until they are used, the desired lazy initialization is already achieved by this:

 private static Singleton instance = new Singleton(); 

If your Singleton class does not contain elements such as constants that can be accessed before the Singleton instance is used first, thatโ€™s all you need to do.

+7
Dec 27 '08 at 11:32
source share

I donโ€™t understand why all people say that double-checking locking is a bad template, but donโ€™t adapt the code so that it works correctly. In my opinion, the code below should work fine.

If someone can tell me if this code suffers from the problem mentioned in Cameron's article, please do.

 public sealed class Singleton { static Singleton instance = null; static readonly object padlock = new object(); Singleton() { } public static Singleton Instance { get { if (instance != null) { return instance; } lock (padlock) { if (instance != null) { return instance; } tempInstance = new Singleton(); // initialize the object with data instance = tempInstance; } return instance; } } } 
+3
Apr 13 '15 at 20:05
source share

I have a double check lock to work using a boolean (e.g. using a primitive to avoid lazy initialization):

A singleton using a boolean does not work. The order of operations observed between different threads is not guaranteed unless you pass through the memory barrier. In other words, as can be seen from the second thread, created = true can be executed before instance= new Singleton();

+2
May 27 '11 at 15:38
source share

I donโ€™t quite understand why there are a bunch of implementation patterns for double checking the lock (apparently, for working with compiler features in different languages). The Wikipedia article on this subject shows a naive method and possible ways to solve the problem, but none of them are so simple (in C #):

 public class Foo { static Foo _singleton = null; static object _singletonLock = new object(); public static Foo Singleton { get { if ( _singleton == null ) lock ( _singletonLock ) if ( _singleton == null ) { Foo foo = new Foo(); // Do possibly lengthy initialization, // but make sure the initialization // chain doesn't invoke Foo.Singleton. foo.Initialize(); // _singleton remains null until // object construction is done. _singleton = foo; } return _singleton; } } 

In Java, you should use synchronized () instead of lock (), but this is basically the same idea. If there is a possible inconsistency when assigning a singleton field, then why not just use the local scope first and then assign the singleton field at the last moment before leaving the critical section? Did I miss something?

Here's the argument of @ michael-borgwardt that in C # and Java a static field is only initialized on first use, but that the behavior is language dependent. And I often used this template to lazily initialize a collection property (e.g. user.Sessions).

+1
Jun 13 2018-12-12T00:
source share

I have a double check lock to work using a boolean (e.g. using a primitive to avoid lazy initialization):

 private static Singleton instance; private static boolean created; public static Singleton getInstance() { if (!created) { synchronized (Singleton.class) { if (!created) { instance = new Singleton(); created = true; } } } return instance; } 
-5
Feb 28 2018-11-21T00:
source share



All Articles