同时使用WeakReference <t>?

时间:2016-03-17 09:47:49

标签: c# .net thread-safety weak-references

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

  

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

但是,我想知道使用WeakReference的实例成员是否确实安全&lt; T&gt;呢?

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

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属性。 (Reference source

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

我在这里算什么安全

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

更明确地说:

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

  • SetTarget不会导致任何异常。

1 个答案:

答案 0 :(得分:2)

By looking at the ecallist.h时如何滑动div我们可以看到WeakTarget / WeakTarget<T>的内部方法已在WeakReferenceNative / WeakReferenceOfTNative个类。查看他们的source code,我们可以看到SetTarget(由AcquireWeakHandleSpinLock setter使用)和GetWeakReferenceTarget中使用了TargetTarget获取者和TryGetTarget

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

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