У меня очень простой вопрос:
безопасно ли читать одновременно экземпляр FrozenDictionary<TKey,TValue>
из разных потоков?
Я предполагаю, что этот тип является потокобезопасным, поскольку он неизменяем, но, как ни странно, его потокобезопасность явно не задокументирована (я не могу найти никаких упоминаний об этом, просматривая официальную документацию . Я смотрю не туда? ).
По моему опыту, потокобезопасность всегда явно документируется в документации Microsoft и никогда не рассматривается как «неявная». Например, потокобезопасность ImmutableDictionary<TKey,TValue>
явно документирована.
Кто-нибудь имеет представление об этом?
Я бы выбрал ImmutableDictionary<TKey,TValue>, мне просто было любопытно.
Следует отметить одну вещь: FrozenDictionary
— это абстрактный класс, а ImmutableDictionary
— запечатанный класс, встроенные реализации должны быть потокобезопасными.
«Обеспечивает неизменяемый словарь, доступный только для чтения» — как это может быть небезопасным для потоков? Если он создается один раз, вы не можете иметь устаревшие данные при его использовании. Я что-то упускаю?
@ Филдор, это именно то, что я понимаю, я просто искал подтверждение из документов.
Я предполагаю, что это просто недосмотр в документации. Если в контракте есть эти требования, единственной проблемой, которую я мог бы себе представить, была бы изменчивость TValue.... так что, может быть, это одна из тех «в основном» потокобезопасных ситуаций? Однако если ваше TValue также неизменяемо, создать проблему будет довольно сложно.
Неизменяемость @Fildor и доступность только для чтения — это внешнее поведение коллекции. Это не гарантирует, что внутренние структуры данных коллекции неизменны. Теоретически возможно, что коллекция оптимизирует внутреннее хранилище данных по соображениям производительности каждый раз, когда считывается ключ. Я считаю, что это маловероятно, но без поддержки документации я не уверен на 100%.
@TheodorZoulias Это звучит разумно, да. Это возвращает нас к «в основном поточно-ориентированному, но, возможно, не всегда»… что можно рассматривать как «достаточно поточно-ориентированному для определенных случаев использования»…
@Fildor «достаточно потокобезопасен для определенных вариантов использования» требует, чтобы варианты использования были конкретными и однозначными. Например, Dictionary<K,V>
является потокобезопасным для чтения, когда нет авторов. Я знаю это, потому что так написано в документации. Без поддержки со стороны документации или, по крайней мере, какого-либо косвенного указания на намерение из другого официального источника (например, GitHub), как мы можем сказать, каковы потокобезопасные варианты использования замороженной коллекции?
@TheodorZoulias "как мы можем сказать, какие варианты использования потокобезопасны" - Мы не можем. ИМХО, это действительно упущение со стороны MS.
@Fildor, если тип / компаратор работает таким образом: это повлияет на любую коллекцию, поэтому: если ImmutableWhatever
можно сделать заявление о потокобезопасности: то же самое можно и FrozenWhatever
@MarcGravell Да, теперь я понимаю. И я полностью согласен с вашими соображениями в вашем ответе.
По моему взвешенному мнению, это ошибка документации, и ее следует устранить соответствующим образом; намерение состоит в том, что я на 99,9% уверен, что это действительно неизменяемая сущность, доступная только для чтения, и если мы игнорируем злоупотребление отражением (поскольку все ставки здесь, на любой тип), это потокобезопасно. Конструктор является внутренним, поэтому нам не нужно беспокоиться об экзотических пользовательских реализациях — только о встроенных реализациях (пустых, маленьких, по умолчанию и т. д.), которые все (при беглом просмотре) кажутся реализованными. соответственно (это не окончательный обзор, заметьте).
ИМХО: зарегистрируйте проблему с документацией
Спасибо за ответ. Интересно, что общедоступный API на самом деле предоставляет что-то, что можно использовать для внутренней модификации. Learn.microsoft.com/en-us/dotnet/api/…
@EnricoMassone Возвращает readonly ref
, поэтому вам придется использовать Unsafe
, чтобы изменить его. А если вы используете небезопасный код, все ставки всегда отключены.
Вы правы, это ссылка только для чтения, а не простая ссылка. Спасибо, что указали на это.
Ваше предположение верно: если какой-либо объект доступен только для чтения и/или вы уверены, что он неизменен и не будет изменен, то я не вижу причин беспокоиться о безопасности потоков. Потокобезопасность означает параллельные операции без возникновения состояний гонки или взаимоблокировок. Если ясно, что объект не будет изменен, то не нужно беспокоиться о его потокобезопасном чтении.
Из данного источника; FrozenDictionary<TKey,TValue> является неизменяемым и оптимизирован для ситуаций, когда словарь создается нечасто, но часто используется во время выполнения. Его создание требует относительно высоких затрат, но обеспечивает превосходную производительность поиска. Таким образом, он идеален для случаев, когда словарь создается один раз, возможно, при запуске приложения, и используется на протяжении всего оставшегося срока службы приложения.
Есть ли причина, по которой вы бы предпочли использовать
FrozenDictionary<,>
вместоImmutableDictionary<,>
, учитывая, что последний дает вам гарантию, которую вы, похоже, ищете?