Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this double-checked locking correct? (.NET)

I have read a lot about the dangers of double checked locking and I would try hard to stay away of it, but with that said I think they make a very interesting read.

I was reading this article of Joe Duffy about implementing singleton with double checked locking: http://www.bluebytesoftware.com/blog/PermaLink,guid,543d89ad-8d57-4a51-b7c9-a821e3992bf6.aspx

And the (variant of) solution he seemed to propose is this:

class Singleton {
private static object slock = new object();
private static Singleton instance;
private static int initialized;
private Singleton() {}
public Instance {
    get {
        if (Thread.VolatileRead(ref initialized) == 0) {
            lock (slock) {
                if (initialized == 0) {
                    instance = new Singleton();
                    initialized = 1;
                }
            }
        }
        return instance;
    }
}

}

My question is, doesn't that still have the danger of writes being reordered? Specifically these two lines:

instance = new Singleton();
initialized = 1;

If those writes are inverted, then some other thread can still read null.

like image 905
ryaner Avatar asked Dec 02 '11 01:12

ryaner


People also ask

What is double checked locking in C#?

Double-checked locking is a pattern meant for reducing the overhead of locking. First, the locking condition is checked without synchronization. And only if the condition is met, the thread will try to get a lock. Thus, the locking would be executed only if it was really necessary.

Is double checked locking safe?

Double-checked locking is a common pattern for lazy initialization of a field accessed by multiple threads.

What is a double lock and why it is used?

In software engineering, double-checked locking (also known as "double-checked locking optimization") is a software design pattern used to reduce the overhead of acquiring a lock by testing the locking criterion (the "lock hint") before acquiring the lock.

Can the double checked locking fail on single processor system?

Ans. There is no mapping of single ton with number of processor of the system. So double check locking will not fail depending on number of processor.


1 Answers

I think the key is in the linked article (http://msdn.microsoft.com/en-us/magazine/cc163715.aspx#S5). Specifically that the MS-implemented .NET 2.0 memory model has the following property:

Writes cannot move past other writes from the same thread.

Duffy mentions that a lot of work was done to support this on the IA-64:

We accomplish this by ensuring writes have 'release' semantics on IA-64, via the st.rel instruction. A single st.rel x guarantees that any other loads and stores leading up to its execution (in the physical instruction stream) must have appeared to have occurred to each logical processor at least by the time x's new value becomes visible to another logical processor. Loads can be given 'acquire' semantics (via the ld.acq instruction), meaning that any other loads and stores that occur after a ld.acq x cannot appear to have occurred prior to the load.

Note that Duffy also mentions that this is an MS-specific guarantee - it's not part of the ECMA spec (at least as of the the article's writing in 2006). So, Mono might not be as nice.

like image 170
Michael Burr Avatar answered Sep 27 '22 19:09

Michael Burr