Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it ok to use following 'thread safe double checked lazy initilalization' pattern?

Framework: .net 4.5

I am using below sample code pattern to initialize variables in thread safe manner. Recently I have been reading some articles which explains 'double checked locking has been broken in some platforms http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html'. But looks like it's OK for me as I am using .net 4.5.

Recommendation as per the comments

Recommendation is to use lazy<T> and let the .net framework do heavy lifting of handling thread safety and memory models based on platforms: http://msdn.microsoft.com/en-us/library/dd642331.aspx

Update

It appears Eric Lippert has been recommending not to use this pattern at all (now am confused) Name for this pattern? (Answer: lazy initialization with double-checked locking) C# manual lock/unlock

Update 2

Following excerpt is "Like all techniques that remove read locks, the code in Figure 7 (similar to the code I have) relies on strong write ordering. For example, this code would be incorrect in the ECMA memory model unless myValue was made volatile because the writes that initialize the LazyInitClass instance might be delayed until after the write to myValue, allowing the client of GetValue to read the uninitialized state. In the .NET Framework 2.0 model, the code works without volatile declarations." From http://msdn.microsoft.com/en-us/magazine/cc163715.aspx

And I am also not using 'volatile' as many examples showed in different code snippets. I am assuming it's OK too (reference: The need for volatile modifier in double checked locking in .NET )

Pseudo-code that explains the version I am using - built on top of .net 4.5:

static private object s_syncObject = new object();
private static string s_lazyInitializedVariable = null;
//is it necessar to make the backing varible volatie?
//private static volatile string s_lazyInitializedVariable = null;
private static string LazyInitializedVariable
{
    get
    {
        if(string.IsNullOrWhiteSpace(s_lazyInitializedVariable))
        {
            lock(s_syncObject)
            {
                if (string.IsNullOrWhiteSpace(s_lazyInitializedVariable))
                {
                    /*
                        * my lazy initialization code
                        */
                    s_lazyInitializedVariable = "Initialized";
                }
            }
        }
        return s_lazyInitializedVariable;
    }
}

I am seeking confirmation of the same. Basically below are my assumptions as I am using .net 4.5

  1. I am assuming it is OK to use the below code and ignore volatile statement? please ratify if my assumptions are OK.

Note: I also noticed that I can make use of lazy<T> introduced in .net 4.0. but as of now will live with the way I am doing I guess, as I have seen the implementation of lazy<T> using ILSpy, and looks like its doing relatively more stuff for simple tasks like mine.

like image 366
Dreamer Avatar asked Nov 11 '22 06:11

Dreamer


1 Answers

Static initialization in the CLR is guaranteed to be thread-safe. Either of the following would be fine for thread-safe initialization:

static string s_lazyInitializedVariable = "Initialized";

If you want it lazy, just use the Lazy class:

static Lazy<string> s_lazyInitializedVariable = new Lazy<string>(() => "Initialized");
like image 85
Dave Black Avatar answered Nov 14 '22 21:11

Dave Black