并发使用弱引用<T>?



WeakReference的文档具有用于线程安全的通用样板:

此类型的任何公共静态(在 Visual Basic 中共享)成员都是线程安全的。不保证任何实例成员都是线程安全的

但是,我想知道无论如何使用弱引用

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

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

此处同时使用 TryGetTargetSetTarget,可能由多个线程同时调用。

它们都在调用由本机代码实现的私有外部Target属性。(参考资料来源)

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


在这里,什么对我来说是安全的

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

更明确地说:

  • TryGetTarget要么返回true并给我一个非空引用;要么false。没有例外。

  • SetTarget不会引起任何异常。

通过查看 ecallist.h,我们可以看到 WeakTarget/WeakTarget<T> 的内部方法是在 WeakReferenceNative/WeakReferenceOfTNative 类中实现的。查看它们的源代码,我们可以看到SetTarget(由Target setter使用)和GetWeakReferenceTarget中都有一个AcquireWeakHandleSpinLock,由Target getter和TryGetTarget使用。

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

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

相关内容

  • 没有找到相关文章

最新更新