Sponsored By Aspose - File Format APIs for .NET

Aspose are the market leader of .NET APIs for file business formats – natively work with DOCX, XLSX, PPT, PDF, MSG, MPP, images formats and many more!

thread safety and static variable instantiation

A coworker asked me a question
today about initialization of static member variables and how they relate to
static constructors.   He also told me about an article he read that the
following code isn’t safe:

 

if( _myObj == null )

{

           
Lock( _lockObj )

           
{

                       
If( _myObj ==  null )

                                   
_myObj = new MyObject(…);

           
}

}

 

He definitely had my attention …
He passed along an article on
implementing a thread-safe singleton pattern in C# and the article is a very interesting
read.  To be fair up front, the above code works in the microsoft
implementation (according to Chriss Brumme and discussed later), but the ECMA
spec is vague on how instantiation must take place.  On the other hand,
the above code is explicitly NOT threadsafe in Java.  The article also
discusses the way in which the .Net runtime chooses to instantiate static
member variables and this section was news to me.

 
Double Locking and Thread Safety

The above code looks right until you read Chris Brumme’s Memory Model
blog
entry
.  The excerpt that finally makes sense after reading this a
couple of times is:

 

… (W)e have to assume that a series of stores have taken
place during construction of ‘a’.   Those stores can be arbitrarily
reordered, including the possibility of delaying them until after the
publishing store which assigns the new object to ‘a’.   At that point,
there is a small window before the store.release implied by leaving the
lock.  Inside that window, other CPUs can navigate through the reference
‘a’ and see a partially constructed instance.

 

So what does this mean?  
In the assignment of a new operator, this piece of code could be broken by a
weak but valid implementation of the ECMA spec.   Given the
following line of code:

 

_myObj = new MyObject();

 

We expect that the underlying
pseudo code looks something like this:

 

Allocate MyObject memory and
assign address to tempObj

Call Constructor on tempObj

assign tempObj to _myObj

 

Given the state of the ECMA spec, a
valid implementation could be this:

 

Allocate MyObject memory and
assign it to _myObj

Call Constructor on _myObj

 

In this second implementation,
consider what happens if the thread holding the lock gets preempted during the
Constructor call.   A thread that doesn’t hold the lock believes the
construction of _myObj is complete and proceeds with a partially initialized variable.

 

If I want to do double check
locking in a truly safe manner that complies with the ECMA spec, I have to
write:

 

 

if( _myObj == null )

{

           
Lock(_lockObj)

           
{

                       
if( _myObj == null )

                       
{

                                   
MyObject tempObj = new MyObject(…);

                                   
_myObj = tempObj;

                       
}

           
}

}

 

As I mentioned earlier, the
Microsoft version of the CLR enables the first version to run correctly (post
.Net 1.0).  Because of the spec, it’s a valid point of concern with
non-Microsoft implementations of the CLR that can be easily answered.  
Given that double-lock checking in Java is not supported, it has me wondering… 
is this a holdover from Java’s days as a stack-based compiler?  Can a
stack-based compiler create an object structure without first allocating the
memory to the host pointer and then calling the constructor?


Static Variable Instantiation

Another interesting part of the article discusses static member instantiation
and how the mechanics work.  Given a class where two static members exist:

public class Ugly
{
    public static Ug _Ug = new  Ug();
    public static Lee _Lee = new Lee();
}

The static variables are not created until I access one of the members which I
would expect.  When I access one of the members before instantiating the
class, both static objects are actually instantiated before returning the
result. This was a surprise to me.   It turns out the C# compiler marks
the class with beforefieldinit.  
(The behaviors surrounding beforefieldinit
are interesting and certainly worth reading.)  The way to get around
this behavior is to define the class as follows:

public UglyClass
{
    public static Ug = new  Ug();
    public static Lee = new Lee();

    static UglyClass() {}
}

When C# sees a static constructor, the type is not marked with the
beforefieldinit attribute.  Therefore each static object is instantiated
upon first reference.

This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

3 Responses to thread safety and static variable instantiation

  1. You don’t need volatile keyword in .NET 1.1+, the Thread.MemoryBarrier method flushes all writes to main memory:

    if( _myObj == null )

    {

    Lock(_lockObj)

    {

    if( _myObj == null )

    {

    MyObject tempObj = new MyObject(…);

    Thread.MemoryBarrier();

    _myObj = tempObj;

    }

    }

    }

  2. Robert says:

    The truest and safest singleton pattern still need the double lock pattern with the addition of using a private static volatile singleton object. The double lock does not count for extremely high volume sights that could have 2 threads entering at the same time, where you must use the volatile keyword so that upon creation it won’t hang around in the registers and get’s committed immediately.

  3. Scott says:

    In 2.0, the model tightened up and makes the sample safe, see “Technique 4: Lazy Initialization” in http://msdn.microsoft.com/msdnmag/issues/05/10/MemoryModels/

Leave a Reply