并发使用WeakReference<T>?

Concurrent use of WeakReference<T>?

WeakReference<T> 的文档具有线程安全的通用样板:

Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

但是,我想知道使用 Wea​​kReference 的实例成员是否真的安全?

特别是,我想知道允许并发访问这样的东西是否安全:

class MyRef<T> where T : class
{
    private readonly Func<Task<T>> _fetcher;
    private readonly WeakReference<T> _wref;

    public MyRef(Func<Task<T>> fetcher, T target = null)
    {
        _fetcher = fetcher;
        _wref = new WeakReference<T>(target);
    }

    public async Task<T> GetTargetAsync()
    {
        T target;

        if (!_wref.TryGetTarget(out target))
        {
            target = await _fetcher();
            _wref.SetTarget(target);
        }

        return target;
    }
}

这里都用到了TryGetTarget and SetTarget,可能是多线程并发调用的

它们都在调用本地代码实现的私有外部Target 属性。 (Reference source)

在我开始使用同步锁保护上述代码之前,我想知道本机实现对于并发访问是否真的不安全。


什么对我来说是安全

简单地说,如果我可以使用上面的代码而不会由于同时调用这两个方法而导致任何意外异常或访问冲突。

更明确地说:

通过查看 ecallist.h we can see that the internal methods of WeakTarget/WeakTarget<T> are implemented in the WeakReferenceNative/WeakReferenceOfTNative classes. Looking at their source code we can see that there is an AcquireWeakHandleSpinLock both in the SetTarget (used by the Target setter) and in the GetWeakReferenceTarget,被 Target getter 和 TryGetTarget 使用。

所以可能整个 Target/TryGetTarget 都是线程安全的(因为它们不会破坏 .NET 的内部结构),但是你需要一个比我更好的程序员来检查它们是否真的是:-)

显然使用 Target/TryGetTarget 不会使目标对象线程安全!那是另一个问题!