C#:volatile读写HashSet

mtk*_*nko 5 .net c# 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));
    }
}
Run Code Online (Sandbox Code Playgroud)

Check经常从多个线程调用方法.Update从单个线程调用方法,该线程监视某些源(数据库,http服务等).这种Volatile.Read / Volatile.Write用法是否正确?

Mar*_*ell 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);
}
Run Code Online (Sandbox Code Playgroud)

  • @CodeCaster我必须同意你是对的,因为文档没有做任何声明,读取不会改变状态; 从技术上讲,*可以*进行某种延迟散列或动态重新平衡; 实际上:它没有 - 但是,是的,我承认这不是这种类型的正式保证 (2认同)