Ok, so I've been looking at the source code for Lazy<T> because I want to extend it. I know that in theory, it is supposed to be thread safe, but I don't know how it can be. Looking it's it .value getter, it does not lock on anything before reading the value.
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();
}
}
It's my understanding that to be thread safe, something must lock when both writing as well as reading, because if a read get's interrupted by a write it can return incorrect data or even have an error. Is this understanding correct, or is something complicated happening with Lazy<T>?