Является ли concurrentMap.keySet(). ToArray() потокобезопасным?
У меня есть ConcurrentHashMap<String, Object> concurrentMap;
Мне нужно вернуть строку [] с ключами карты.
Это следующий код:
public String[] listKeys() {
return (String[]) concurrentMap.keySet().toArray();
}
поток безопасно?
2 ответа
Да и нет. Threas-safe определяется только нечетко, как только вы расширяете область действия.
Как правило, параллельные коллекции реализуют все свои методы таким образом, чтобы обеспечить одновременный доступ для нескольких потоков или, если они не могут, предоставить механизмы для прозрачной сериализации таких обращений (например, синхронизации). Таким образом, они безопасны в том смысле, что они гарантируют, что они сохраняют действительную внутреннюю структуру, а вызовы методов дают действительные результаты.
Нечеткость начинается, если вы посмотрите на детали, например, toArray() вернет вам своего рода снимок содержимого коллекций. Нет гарантии, что к тому времени, когда метод вернётся, содержимое уже не будет изменено. Таким образом, хотя вызов является потокобезопасным, результат не будет соответствовать обычным инвариантам (например, содержимое массива может не совпадать с коллекцией).
Если вам нужна согласованность по объему многократных вызовов для одновременной коллекции, вам необходимо предоставить механизмы в коде, вызывающие методы, чтобы обеспечить требуемую согласованность.
В то время как ConcurrentHashMap
это потокобезопасный класс, Iterator
то, что используется на ключах, НЕ МОЖЕТ БЫТЬ синхронизировано с любым последующим HashMap
изменения, однажды созданные...
Из спецификации:
public Set<K> keySet()
Returns a Set view of the keys contained in this map......
...........................
The view's iterator is a "weakly consistent" iterator that will
never throw ConcurrentModificationException, and guarantees to
traverse elements as they existed upon construction of the iterator,
and may (but is not guaranteed to) reflect any modifications
subsequent to construction.