好的,所以我一直在查看Lazy
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();
}
}
我的理解是,为了线程安全,在写入和读取时都必须锁定某些内容,因为如果读取被写入中断,则可能会返回不正确的数据甚至出现错误。这种理解是正确的,还是Lazy
对引用类型的变量的读/写是原子的,因此即使没有锁定,这样的读取也不可能返回未写入的值。 在那里读取的值只分配一次,当 Lazy 生成其值时,所以要么值是 null
,然后它移动到更复杂的逻辑,要么不是,我们已经有一个值要返回。 如果它继续前进,它实际上使用锁定机制来确保多个线程不会同时尝试创建值。