[Mono-devel-list] What to do with TypeInitialization in case of exceptions on second attempt to access class ? Singleton pattern

Ben Maurer bmaurer at ximian.com
Mon Oct 25 17:49:04 EDT 2004


On Mon, 2004-10-25 at 14:29 -0700, gennady wexler wrote:
> you need to exit lock() before you return, otherwise you lock in critical
> section forever. 
> 
> perhaps like this?
> 
> public static Singleton Instance  {
>   get {
>     lock (typeof(Singleton)) {
>       if  (Singleton.instance == null)
>         Singleton.instance = new Singleton();
>      }
>      return Singleton.instance; 
>   }
> }
> 
Lock is implemented as try/finally, so you catch it before you return.

[nb, you are technically not able to `ret' out of a critical section. c#
generates a leave which jumps to a ret]

However, if you have a multi-threaded app, it is best to optimize this
pattern. There are a few ways to do this:

1) Use Interlocked.CompareExchange
if (Singleton.instance == null)
    Interlocked.CompareExchange (ref Singleton.instance, new Singleton (), null);
return Singleton.instance

This is the fastest thread-safe way to do it. 

2) use the double-checked lock
If you declare Singleton.instance as `volatile' and do
if (Singeton.instance == null)
    lock (typeof (Singeton)
       if (Singleton.instance == null)
             Singleton.instance = new Singleton ();

The only advantage of this over 1 is that there is 0 chance that two
singletons will be created and that one gets thrown away. If singleton
is extremely expensive to initialize (or has side affects), you can use
this rather than 1.

Also, I would note that doing lock (typeof (Singleton)) is a *bad idea*.
Type objects can be shared across app domains (they are in the MSFT
impl, we have not done that yet). So, locking Singleton could
effectively lock it in another app domain (not a good thing). Also, its
hard to check if anyone else does lock (typeof (Singleton)) in any other
places in code. It is best to do:

static readonly object my_lock = new object ();

lock (my_lock) {
}

(or use the compare exchange impl)

-- 
Ben Maurer <bmaurer at ximian.com>




More information about the Mono-devel-list mailing list