如果我监视.当另一个线程处于临界区而没有锁时,有条件进入

本文关键字:有条件 临界区 监视 另一个 线程 如果 | 更新日期: 2023-09-27 18:12:07

我试图从系统类(Lazy<T>)重新实现功能,我发现了这段不寻常的代码。我明白了基本的意思。第一个尝试获取值的线程执行计算。在此期间尝试的任何线程都被锁定在gate上,等待释放,然后去获取缓存的值。以后的调用都会注意到哨兵值,不再为锁操心了。

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); 
    }
}

但是,假设在代码更改之后,另一个方法将this._locker重置为原始值,然后进入锁定并重新计算缓存的值。当它这样做时,另一个线程碰巧正在获取缓存的值,所以它在锁定的部分内,但没有锁。会发生什么呢?它只是正常执行,而线程与锁也并行?

如果我监视.当另一个线程处于临界区而没有锁时,有条件进入

当它这样做的时候,另一个线程碰巧正在获取缓存的值,所以它在锁定的区域内,但是没有锁。会发生什么呢?它只是正常执行,而线程与锁也并行?

是的,它会正常执行。

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

基本上,整个代码可以替换为:
// Have a field like the following:
Lazy<object> cachedValue = new Lazy<object>(() => SomeCalculations());
// Code then becomes:
return cachedValue.Value;