Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memory Model Guarantees in Double-checked Locking

I recently came across the following post on the Resharper website. It was a discussion of double-checked locking, and had the following code:

public class Foo
{
    private static volatile Foo instance;
    private static readonly object padlock = new object();

    public static Foo GetValue()
    {
        if (instance == null)
        {
            lock (padlock)
            {
                if (instance == null)
                {
                    instance = new Foo();
                    instance.Init();
                }
            }
        }
        return instance;
     }

     private void Init()
     {
        ...
     }
}

The post then makes the claim that

If we assume that Init() is a method used to intialize the state of Foo, then the above code may not function as expected due to the memory model not guaranteeing the order of reads and writes. As a result, the call to Init() may actually occur before the variable instance is in a consistent state.

Here are my questions:

  1. It was my understanding that .NET memory model (at least since 2.0) has not required that instance be declared as volatile, since lock would provide a full memory fence. Is that not the case, or was I misinformed?

  2. Isn't read/write reordering only observable with respect to multiple threads? It was my understanding that on a single thread, the side effects would be in a consistent order, and that the lock in place would prevent any other thread from observing something to be amiss. Am I off-base here as well?

like image 242
dlev Avatar asked Aug 26 '11 21:08

dlev


People also ask

What is the use of double-checked locking in singleton?

Double checked locking of Singleton is a way to make sure that only one instance of Singleton class is created through an application life cycle.

Is double-checked locking safe?

Since only the first access requires locking, double-checked locking is used to avoid locking overhead of subsequent accesses. However, on many languages and hardware, the design can be unsafe.

What is double locking mechanism?

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 double-checked locking fail?

No matter how you rig it, double-checked locking still fails Unfortunately, DCL isn't guaranteed to work under the current Java Memory Model (JMM.)


1 Answers

The big problem with the example is that the first null check is not locked, so instance may not be null, but before Init has been called. This may lead to threads using instance before Init has been called.

The correct version should therefore be:

public static Foo GetValue()
{
    if (instance == null)
    {
        lock (padlock)
        {
            if (instance == null)
            {
                var foo = new Foo();
                foo.Init();
                instance = foo;
            }
        }
    }

    return instance;
 }
like image 153
Tim Lloyd Avatar answered Sep 18 '22 06:09

Tim Lloyd