Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#: volatile reads and writes of HashSet

I have a 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));
    }
}

Method Check is called from multiple threads quite often. Method Update is called from a single thread which monitors some source (database, http service etc.). Is this pattern of Volatile.Read / Volatile.Write usage correct?

like image 410
mtkachenko Avatar asked Feb 14 '19 12:02

mtkachenko


1 Answers

If you mean "will Check always use the most up to date version of the field", then yes, as a side-effect of volatility this will be the case - and swapping the entire reference is much cheaper than constantly synchronizing (.NET ensures you can't have a torn reference so the reference swap is guaranteed to be atomic).

Note: the thread-safety in this scenario is strictly dependent on the fact that the hash-set is not mutated after it has been created and the reference swapped, which is what happens in the code in the question.

You can get the same result more conveniently, though, by declaring the field as 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);
}
like image 161
Marc Gravell Avatar answered Sep 30 '22 00:09

Marc Gravell