[Mono-list] Class library developers: locking issues to keep in mind

Alexander Klyubin klyubin@aqris.com
Sun, 28 Oct 2001 10:20:47 +0000

I don't know that much about .NET memory model as of Java's one, but in 
Java the code with on-demand locking you provided is called 
Double-checked Locking (DCL). The problem with it is that it is not 
guaranteed to work in all JVMs as synchronizing memory thread's own 
local memory with shared main memory accessible to all threads can work 
differently in different JVMs. Maybe memory model is organized 
differently in .NET languages compared to Java. But as similarity 
between C# and Java is realy big, I suspect memory model should be quite 
similar if not the same.

Here are good articles on this topic for Java. You migh also want to 
find out more by simply searching JavaWorld (www.javaworld.com) for 
"DCL". But these two are the core ones to understand the problem:

1. Double-checked locking: Clever, but broken

2. Can double-checked locking be fixed?

Alexander Klyubin

Miguel de Icaza wrote:

>    I noticed today that I have been writing thread-unsafe code in my
> code that goes into the class libraries.  Some classes for example
> provide static properties, and to avoid a costly initialization at
> bootstrap time, you want to create some of those values on demand
> instead of doing it constructor, like this:
>    class Sample {
> 	static SomeObject MyProperty {
> 		get {
> 			if (some_object == null)
> 				some_object = new SomeObject ();
> 			return some_object;
> 		}
> 	}
>    }
>    Well, it turns out that the code above is not thread safe, because
> two threads might be hitting the same spot at the same time and two
> copies of SomeObject would be created.  Then later on, comparissions
> would not work (if p == MyProperty).  To correct that situation, you
> have to lock on either the instance (this) or the class (typeof (this)),
> like this:
>     class Sample {
> 	static SomeObject MyProperty {
> 		get {
> 			if (some_object != null)
> 				return some_object;
> 			lock (typeof (Sample)){
> 				if (some_object == null)
> 					some_object = new SomeObject ();
> 				return some_object;
> 			}
> 		}
> 	}
>     }
>    Notice that you first test for initialization: if it is not null, you
> can return the value without ever locking.  You only lock (which is an
> expensive operation) if the value needs to be computed.
>    Now, notice how we test for the value *inside* the lock.  This is
> important because the value might have been initialized in a separate
> thread before we reach lock.
> Miguel.
> _______________________________________________
> Mono-list maillist  -  Mono-list@ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-list