Краткий ответ: Нет .
Немного более длинный ответ: поскольку add () и clear () никоим образом не синхронизированы, а HashSet сам по себе не синхронизирован, возможно, что несколько потоков будут в них одновременно.
Редактировать следующий комментарий : Ах. Теперь короткий ответ - Да, Сорта . :)
Причина "сорта" (американский сленг означает частично, кстати) заключается в том, что две операции могут быть атомарно безопасными, но небезопасными при использовании в комбинации для выполнения сложной операции.
В данном примере, где поддерживаются только add () и clear (), этого не может быть.
Но в более полном классе, где у нас было бы больше интерфейса Collection, представьте вызывающую программу, которой нужно добавить запись в набор, если в наборе уже не более 100 записей.
Этот вызывающий объект хотел бы написать метод примерно так:
void addIfNotOverLimit (AmIThreadSafe set, Object o, int limit) {
if (set.size() < limit) // ## thread-safe call 1
set.add(o); // ## thread-safe call 2
}
Проблема в том, что, хотя каждый вызов сам по себе является потокобезопасным, два потока могут быть в addIfNotOverLimit (или, в этом отношении, добавление через другой метод вообще), и поэтому потоки A будут вызывать size () и получать 99, а затем вызывать add (), но до того, как это произойдет, он может быть прерван, и поток B мог бы добавить запись, и теперь набор превысил бы свой предел.
Мораль? Сложные операции усложняют определение «потокобезопасности» .