C# 使用 Lazy Initialization 和 lock 在一起

C# using Lazy Initialization and lock together

我希望我的一些对象延迟初始化,例如:

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

而且我不希望多个线程在初始化后访问这个对象。我是否也应该使用锁定机制来防止这种情况发生,或者 Lazy 是否以这种方式支持线程安全?同时使用 Lazy 和 lock 似乎不是正确的方法。

docs中声明“使惰性对象线程安全并不能保护惰性初始化对象。如果多个线程可以访问惰性初始化对象,则必须使其属性和多线程访问安全的方法。"

是否正在编写一个自定义类型,它是一种惰性类型并且每次都锁定 engine.Value 被称为合乎逻辑的事情?举个例子:

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;
            }
        }
    }
}

用法:

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

您的 Lazy<T> 专业化没有提供额外的好处。突出显示的问题如下:

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

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

t1.Start();
t2.Start();

很明显,在你得到你的值之后,懒惰在它的操作中不再发挥任何作用,如果这个值要跨多个线程使用,你需要在它的方法和属性中编写额外的守卫。