C# 当另一个线程处于没有锁的关键部分时,如果我监视。有条件地输入会发生什么?

C# 当另一个线程处于没有锁的关键部分时,如果我监视。有条件地输入会发生什么?,c#,.net,multithreading,C#,.net,Multithreading,我试图从一个系统类(Lazy)重新实现功能,我发现了这段不同寻常的代码。我知道基本的想法。尝试获取值的第一个线程执行计算。在发生这种情况时尝试的任何线程都会被锁定,等待释放,然后获取缓存的值。以后的任何调用都会注意到sentinel值,不再为锁操心 bool lockWasTaken = false; var obj = Volatile.Read<object>(ref this._locker); object returnValue = null; try { if

我试图从一个系统类(
Lazy
)重新实现功能,我发现了这段不同寻常的代码。我知道基本的想法。尝试获取值的第一个线程执行计算。在发生这种情况时尝试的任何线程都会被锁定,等待释放,然后获取缓存的值。以后的任何调用都会注意到sentinel值,不再为锁操心

bool lockWasTaken = false;
var obj = Volatile.Read<object>(ref this._locker);
object returnValue = null;

try
{
    if (obj != SENTINEL_VALUE)
    {
        Monitor.Enter(obj, ref lockWasTaken);
    }

    if (this.cachedValue != null) // always true after code has run once
    {
        returnValue = this.cachedValue;
    }
    else //only happens on the first thread to lock and enter
    {
        returnValue = SomeCalculations();
        this.cachedValue = returnValue;
        Volatile.Write<object>(ref this._locker, SENTINEL_VALUE);
    }
    return returnValue
}
finally
{
    if (lockWasTaken)
    {
        Monitor.Exit(obj); 
    }
}
bool lockwastake=false;
var obj=Volatile.Read(参考本文件);
对象返回值=null;
尝试
{
if(obj!=哨兵_值)
{
监视器。输入(obj,参考锁定已采取);
}
if(this.cachedValue!=null)//在代码运行一次后始终为true
{
returnValue=this.cachedValue;
}
else//只发生在第一个要锁定和进入的线程上
{
returnValue=SomeCalculations();
this.cachedValue=返回值;
Volatile.Write(参考此._locker,SENTINEL_值);
}
返回值
}
最后
{
如果(上锁)
{
监控出口(obj);
}
}
但假设在代码发生更改后,另一个方法将
this.\u locker
重置为其原始值,然后锁定并重新计算缓存的值。当它执行此操作时,另一个线程碰巧正在拾取缓存的值,因此它位于锁定的部分内,但没有锁定。会发生什么?当带锁的线程也并行运行时,它是否正常执行

当它执行此操作时,另一个线程碰巧正在拾取缓存的值,因此它位于锁定的部分内,但没有锁定。会发生什么?当带锁的线程也并行运行时,它是否正常执行

是的,它会正常执行

这就是说,这段代码似乎可以通过使用完全删除。
Lazy
类提供了一种线程安全的方法来处理数据的延迟实例化,这似乎是该代码的目标

基本上,整个代码可以替换为:

// Have a field like the following:
Lazy<object> cachedValue = new Lazy<object>(() => SomeCalculations());

// Code then becomes:
return cachedValue.Value;
//具有如下字段:
Lazy cachedValue=新的Lazy(()=>SomeCalculations());
//然后代码变为:
返回cachedValue.Value;

它实际上是来自
Lazy
类的代码。我正在重新实现它,以制作一个可以重置的版本。使用现有的Lazy类有相当简单的方法,但我认为这会很有趣,也是一种尝试多线程代码的好方法。