C# 懒惰怎么可能<;T>;在';s.value属性不锁定?

C# 懒惰怎么可能<;T>;在';s.value属性不锁定?,c#,multithreading,C#,Multithreading,好的,我一直在看,因为我想扩展它。我知道在理论上,它应该是线程安全的,但我不知道怎么可能。看起来就是这样。值获取程序,在读取值之前不会锁定任何内容 public T Value { get { Boxed boxed = null; if (m_boxed != null ) { // Do a quick check up front for the fast path. boxed

好的,我一直在看,因为我想扩展它。我知道在理论上,它应该是线程安全的,但我不知道怎么可能。看起来就是这样。值获取程序,在读取值之前不会锁定任何内容

public T Value
{
    get
    {
        Boxed boxed = null;
        if (m_boxed != null )
        {
            // Do a quick check up front for the fast path.
            boxed = m_boxed as Boxed;
            if (boxed != null)
            {
                return boxed.m_value;
            }
              LazyInternalExceptionHolder exc = m_boxed as LazyInternalExceptionHolder;
            Contract.Assert(m_boxed != null);
            exc.m_edi.Throw();
        }

        // Fall through to the slow path.
#if !FEATURE_CORECLR
        // We call NOCTD to abort attempts by the debugger to funceval this property (e.g. on mouseover)
        //   (the debugger proxy is the correct way to look at state/value of this object)
        Debugger.NotifyOfCrossThreadDependency(); 
#endif
        return LazyInitValue();

    }
}

我的理解是,为了线程安全,在写入和读取时都必须锁定某些内容,因为如果读get被写入中断,它可能返回不正确的数据,甚至出现错误。这种理解是正确的,还是Lazy发生了一些复杂的事情?

对引用类型的变量的读/写是原子的,因此,即使没有锁定,这种读取也不可能返回未写入的值。在那里读取的值只有一次赋值,当Lazy生成它的值时,因此要么该值为
null
,它将转到更复杂的逻辑,要么不是,我们已经有一个值要返回。如果继续,它确实使用了锁定机制来确保多个线程不会同时尝试创建值。

我认为这是双重检查锁定,对吗?@Lukazoid:这是双重检查锁定的一种变体。如果你阅读代码,你会看到m_boxed在锁外和锁内都被检查为空,因此有一个双重检查。你所看到的代码只是双重检查锁模式的一个变体,它是安全的,如标记的副本中所述。要了解更多信息,您可能需要阅读其他Q&A,例如,并且“复杂的东西”在LazyInitValue中。这就是在面对多个线程时确保正确性的神奇之处。您关于线程安全需要在读写时锁定的说法是错误的。这段代码是一个锁省略模式的示例,由专家编写,他们精确地知道确保正确性和高性能所需的内存屏障、读写顺序,并且它被狭隘地调整到计算一次并发布到属性的特定场景。不要试图自己编写这样的代码!如果您试图使某个线程安全,请始终如一地解除锁定。@EricLippert,我的一位同事建议使用Volatile.Read来访问在一个线程和另一个线程上分配的惰性线程。你的想法?这里有一些代码:public类{private Lazy{u prop1;public void Init(){u prop1=InterlockedExchange(ref{u prop1,new Lazy(=>new SomeType());}public SomeType GetSomeType(){return{u prop1.Value;}@SimonGillbee:懒散地初始化Lazy类型的字段不会让你觉得有点奇怪吗?为什么不急切地初始化它呢?