2014-11-25 1 views
9

Если я инициализирую HashSet<> внутри инициализатора Lazy, а затем никогда не меняет его содержимое, то HashSet<> по сути потокобезопасен? Существуют ли операции чтения, требующие блокировки?Является ли HashSet только для чтения неотъемлемо потокобезопасным?

Аналогичный вопрос Java here для коллекций в целом, который по существу говорит «да», но с некоторыми оговорками (которые не применяются в этой ситуации).

+1

Да еще раз, если он действительно не меняется, в то время как строится не доступен, то да вам будет хорошо. Тем не менее, нет ничего, что помешало бы кому-то изменить его, поэтому его «чистое» поведение неукреплено. Попробуйте неизменные коллекции. –

+0

@AdamHouldsworth, к сожалению, неизменные коллекции имеют ужасающую производительность http://ayende.com/blog/164739/immutable-collections-performance –

+0

@ChrisMarisic Плохая производительность довольно известна. При этом для многих сценариев проблемы с производительностью не будут возникать. Вы всегда можете реализовать свою собственную, обернув внутри себя неизменяемые коллекции, которые на протяжении многих лет применяли к ним много оптимизаций. –

ответ

10

Да, это так. Пока строительство объекта HashSet является потокобезопасным, доступ к нему всегда будет безопасным потоком, пока содержимое не изменится.

Если вы initialize в Lazy с помощью LazyThreadSafetyMode.PublicationOnly вы можете быть уверены, что инициализация Lazy является поточно.

Когда несколько потоков пытаются инициализировать экземпляр Lazy<T> одновременно, все потоки могут выполняться методом инициализации (или конструктор по умолчанию, если не существует метод инициализации). Первый поток для завершения инициализации задает значение экземпляра Lazy<T>. Это значение возвращается к любым другим потокам, которые одновременно запускали метод инициализации, если только метод инициализации не генерирует исключения из этих потоков.

Небольшой пример кода:

var l = new Lazy<HashSet<string>>(() => new HashSet<string>() { "a" } 
           , LazyThreadSafetyMode.PublicationOnly 
           ); 
+0

Хотя я верю, что на практике это правда, я не могу найти гарантию того, что не изменяющиеся операции HashSet являются потокобезопасными. На самом деле в документации HashSet указано иначе: https://msdn.microsoft.com/en-us/library/bb359438(v=vs.110).aspx «Любые члены экземпляра не гарантируют безопасность потоков». У вас есть доказательства того, что в этом случае гарантируется безопасность потоков? – Pagefault