C#:HashSet的易失性读写

时间:2019-02-14 12:20:36

标签: c# .net multithreading volatile

我有一堂课

public class Checker
{
    private HashSet<int> _hs = new HashSet<int>();

    public bool Check(int a)
    {
        return Volatile.Read(ref _hs).Contains(a);
    }

    public void Update(IEnumerable<int> items)
    {
        Volatile.Write(ref _hs, new HashSet<int>(items));
    }
}

方法Check经常从多个线程中调用。方法Update是从监视某个源(数据库,http服务等)的单个线程中调用的。这种Volatile.Read / Volatile.Write使用模式正确吗?

1 个答案:

答案 0 :(得分:5)

如果您的意思是“将Check始终使用该字段的最新版本”,那么是的,因为这种情况会导致波动,因此替换整个引用要便宜得多而不是不断同步(.NET确保您的引用不会撕裂,因此可以保证引用交换是原子的)。

注意:在这种情况下,线程安全性严格取决于散列集在创建和引用交换后不发生突变的事实,这在代码中会发生问题。

通过将字段声明为volatile,您可以更方便地获得相同的结果:

public class Checker
{
    private volatile HashSet<int> _hs = new HashSet<int>();

    public bool Check(int a) => _hs.Contains(a);

    public void Update(IEnumerable<int> items) => _hs = new HashSet<int>(items);
}