Страницы

Поиск по вопросам

пятница, 3 января 2020 г.

Dictionary<KeyType,ValueType> является ли потокобезопасным для чтения?

#c_sharp #многопоточность


Является ли Dictionary потокобезопасным для чтения и перебора
значений?

То есть записи в этот Dictionary не будет (инициализируется только при запуске проекта),
и хочу понять можно ли его использовать в контексте singleton сервиса в ASP.NET Core 2.0? 
    


Ответы

Ответ 1



https://msdn.microsoft.com/en-us/library/xfhwa508(v=vs.110).aspx Thread Safety A Dictionary can support multiple readers concurrently, as long as the collection is not modified. то есть Потокобезопасность ... поддерживает несколько одновременных операций чтения, постольку поскольку данные не изменяются.

Ответ 2



Смотрите, сам по себе словарь является потокобезопасным для случая, когда у вас есть лишь операции чтения из разных потоков. Однако для случая, когда вам ещё нужна инициализация, необходимо учитывать возможные «гонки» между инициализирующим потоком, и потоком, который читает уже инициализированный словарь. Рассмотрим такой код: var dict = Dictionary(); dict[k1] = v1; // инициализация GlobalAccessibleDict = dict; // публикация Я проштудировал спецификацию и не нашёл пункта, который запрещал бы компилятору переставить инициализацию и публикацию, ведь с точки зрения публикующего потока от перестановки этих присваиваний смысл кода не меняется. Таким образом, с точки зрения другого, читающего потока инициализация может произойти слишком поздно. Итак, судя по всему, с точки зрения языка этот паттерн неправильный, и может привести к чтению другим потоком недоинициализированного словаря. Для того, чтобы быть уверенныйм, необходимо использовать lock (или, возможно публикацию через volatile-поле). С другой стороны, с точки зрения имплементации в Microsoft .NET, статья Joe Duffy CLR 2.0 memory model утверждает, что в имплементации .NET 2.0 Rule 2: All stores have release semantics, i.e. no load or store may move after one. то есть, перестановки записей в переменные недопустимы. Если я правильно понял этот текст, это означает, что гонка, описанная мной, невозможна, и инициализация закончится строго до публикации. Поэтому с хорошей долей вероятности в текущей реализации (а модель памяти .NET 4.0 вроде бы не слабее) в вашем подходе всё хорошо. (Я не нашёл, однако, ничего про порядок актуализации данных в других потоках, так что тонкости остаются.)

Комментариев нет:

Отправить комментарий