C#使用Lazy Initialization并锁定在一起

时间:2015-10-20 11:30:48

标签: c# multithreading lazy-initialization

我希望我的一些对象延迟初始化为:

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

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

docs中声明&#34; 使Lazy对象线程安全无法保护延迟初始化对象。如果多个线程可以访问延迟初始化的对象,则必须使其属性和方法对多线程访问安全。&#34;

编写一个懒惰类型的自定义类型并且每次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();
})

1 个答案:

答案 0 :(得分:2)

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

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

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

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

显然,在你获得了你的值之后,懒惰在其操作中不再发挥作用,如果要在多个线程中使用该值,则需要在其方法和属性中编写额外的防护。