Search code examples
c#multithreadinglazy-initialization

C# using Lazy Initialization and lock together


I want some of my objects lazy initialized like:

private static Lazy<MappingEngine> engine = new Lazy<MappingEngine>(() =>
{
    return new MappingEngine();
})

And I don't want multiple threads to access to this object after it is initialized. Should I also use lock mechanism to prevent that too or does Lazy supports the thread-safety in that manner? Using both Lazy and lock together did not seem the right way to do.

In docs it is stated that "Making the Lazy object thread safe does not protect the lazily initialized object. If multiple threads can access the lazily initialized object, you must make its properties and methods safe for multithreaded access."

Is writing a custom type which is a lazy type and which puts lock on everytime engine.Value is called a logical thing to do? To give an example:

public class MyLazyType<T> : Lazy<T>
{
    private object lockObj = new object(); //not static since the reference to this class will be

    public MyLazyType(Func<T> valueFactory) : base(valueFactory)
    {

    }

    public new T Value
    {
        get
        {
            lock (lockObj)
            {
                return base.Value;
            }
        }
    }
}

Usage:

private static MyLazyType<MappingEngine> engine = new MyLazyType<MappingEngine>(() =>
{
    return new MappingEngine();
})

Solution

  • Your specialization of Lazy<T> offers no additional benefit. The problem being highlighted is as follows:

    var t1 = new Thread(()=>{
        myLazy.Value.SomeNonThreadsafeMethod();
    });
    
    var t2 = new Thread(()=>{
        myLazy.Value.SomeNonThreadsafeMethod();
    });
    
    t1.Start();
    t2.Start();
    

    Clearly, after you've got your value, the lazy plays no further part in its operation and you'll need to write additional guards in its methods and properties if the value is to be used across several threads.