C #: volatile читает и пишет HashSet - PullRequest
0 голосов
/ 14 февраля 2019

У меня есть класс:

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 голосов
/ 14 февраля 2019

Если вы имеете в виду «будет 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...