2017-02-18 17 views
4

Я работаю на Java 7.HashSet и многопоточность

Я хочу знать, если метод contains потокобезопасно на объекте HashSet.

HashSet инициализируется одним потоком. Затем мы обертываем HashSet немодифицируемой коллекцией (Collections.unmodifiableSet). После инициализации несколько потоков вызывают только метод contains.

Когда я читаю Джавадока, это неясно для меня.

На HashSet Javadoc мы можем читать

Этот класс реализует интерфейс Set, поддержанный хэш-таблицей (фактически экземпляр HashMap).

...

Обратите внимание, что эта реализация не синхронизируется.

А на HashMap Javadoc, мы можем прочитать:

Обратите внимание, что эта реализация не синхронизирована. Если несколько потоков обращаются к карте хешей одновременно, и по крайней мере один из потоков изменяет структуру структурно, она должна быть синхронизирована извне. (структурная модификация любая операция, которая добавляет или удаляет один или несколько отображений, просто изменяя значение, связанное с ключом, который экземпляр уже содержит не структурная модификация.)

Для меня это означает, что метод contains не является структурной модификацией.

Таким образом, множественный вызов метода contains это поточно-безопасный?

Если это правда: гарантируется ли она на всех реализациях JVM (например, IBM JVM)?

+2

Это не имеет значения, если поток не делает структурные изменения: если какой-то другой поток делает структурные изменения, вам необходимо синхронизировать * все * доступ из * любого * потока, включая вызовы 'contains'. –

+0

Даже если мы используем 'Collections.unmodifiableSet' при инициализации HashSet? На самом деле, мы уверены, что в нашем случае мы используем только метод 'contains'. для того, чтобы быть ясным: вся нить, которая использует HashSet (после инициализации), использует только метод 'contains' – lecogiteur

+1

", если какой-либо другой поток выполняет структурные изменения ". Если вы сразу же завершите набор в немодифицируемом наборе при строительстве, ни одна из других нитей не будет выполнять структурные изменения. –

ответ

2

В общем, не может быть никакой параллельной гонки (и, следовательно, конфликта) исключительно между операциями чтения. Проблемы параллелизма возникают между операциями чтения и записи. Таким образом, чередование нескольких операций чтения всегда является потокобезопасным (если мы предположим, что такое понятие безопасности потока хорошо определено).

Теперь есть еще один случай, когда может возникнуть проблема параллелизма, и это происходит во время инициализации структуры данных, поскольку это можно рассматривать как единственную модификацию (операцию записи) в вашем случае. Чтобы убедиться, что все последующие вызовы будут видеть полностью инициализированный набор, вы должны убедиться, что он правильно инициализирован. Эта концепция определена как «безопасная публикация» на Java, и вы можете узнать об этом более подробно here или в книге "Java Concurrency in Practice" книга.

В заключение, Collections.unmodifiableSet() публикует результат безопасным путем через поле final.Итак, да, вы можете быть уверены, что все будет видеть полностью инициализирован Set