C#:HashSet的volatile读写
C#: volatile reads and writes of HashSet
我有一个 class:
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
这种用法是否正确?
如果你的意思是 "will Check
always use the most up to date version of the field",那么是的,作为波动的副作用,情况就是如此 - 并且交换整个引用比不断同步便宜得多(.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);
}
我有一个 class:
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
这种用法是否正确?
如果你的意思是 "will Check
always use the most up to date version of the field",那么是的,作为波动的副作用,情况就是如此 - 并且交换整个引用比不断同步便宜得多(.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);
}