Kev*_*vin 10 .net c# weak-references thread-safety
作为一名经验丰富的C++程序员试图习惯于.NET,微软的WeakReference"Target"属性中有一个实现细节,这让我很烦恼......
public class WeakReference : ISerializable
{
internal IntPtr m_handle;
internal bool m_IsLongReference;
...
public virtual object Target
{
[SecuritySafeCritical]
get
{
IntPtr handle = this.m_handle;
if (IntPtr.Zero == handle)
{
return null;
}
object result = GCHandle.InternalGet(handle);
if (!(this.m_handle == IntPtr.Zero))
{
return result;
}
return null;
}
[SecuritySafeCritical]
set
{
IntPtr handle = this.m_handle;
if (handle == IntPtr.Zero)
{
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
}
object oldValue = GCHandle.InternalGet(handle);
handle = this.m_handle;
if (handle == IntPtr.Zero)
{
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
}
GCHandle.InternalCompareExchange(handle, value, oldValue, false);
GC.KeepAlive(this);
}
}
...
}
Run Code Online (Sandbox Code Playgroud)
困扰我的是这个 - 为什么他们两次检查m_handle的有效性?特别是在'set'方法中 - 在方法结束时使用GC.KeepAlive应该保持WeakReference不被垃圾收集,从而使句柄保持非零 - 对吗?
在'get'的情况下 - 一旦我们通过InternalGet实际检索了对目标的引用,为什么还要再次检查原始的m_handle值呢?我可以想到的是,或许他们正试图防止WeakReference在InternalGet期间或之后被处理和最终确定 - 但是当然,在我们到处返回对象之前,它是否也不能被处理和最终确定?我只是不能提出一个有效的解释,为什么这里需要进行双重检查......
我所能想到的可能是他们试图防止在InternalGet期间或之后处理和最终确定WeakReference
这是完全正确的.
但可以肯定的是,在我们回到对象之前,它是否也不能被处理和最终确定?
不,因为在那时,必须已经为对象创建了一个强指针.InternalGet返回一个强指针,如果该指针存储在oldValue该对象中,那么垃圾收集器现在无法再回收该对象.
| 归档时间: |
|
| 查看次数: |
699 次 |
| 最近记录: |