我有一堂课
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
使用模式正确吗?
答案 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);
}