如果我监视.当另一个线程处于临界区而没有锁时,有条件进入
本文关键字:有条件 临界区 监视 另一个 线程 如果 | 更新日期: 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;