Поведение clear()
в этом контексте не определено 1 . Javadoc состояния:
"Для агрегатных операций, таких как putAll и clear, одновременный поиск может отражать вставку или удаление только некоторых записей."
Глядя на исходный код, clear()
реализуется путем очистки каждого из сегментов по одному. Каждый сегмент заблокирован во время очистки, но на всей карте нет блокировки. Это означает, что другой поток может добавить записи в только что очищенный сегмент до того, как общий вызов clear()
вернется.
Таким образом, на практике любой из предлагаемых вами результатов / вариантов поведения возможен в зависимости от размера карт, распределения ключей между сегментами, используемой вами версии Java и ... времени.
Внутренне ли он блокирует все строки и помечает каждый ключ для удаления?
Нет. Каждый сегмент заблокирован (по одному за раз), а записи в сегменте удалены. (Это делается для того, чтобы избежать аномалий памяти, которые могут повредить цепочки хеширования сегментов и т. Д.)
Относительно этого:
synchronized (this) {
myMap.clear();
}
Это не будет препятствовать другим элементам вставлять элементы во время выполнения clear()
. Это просто остановит одновременную очистку двух потоков (выполняющих один и тот же код).
Если вы хотите гарантировать, что clear()
очистит карту, вам нужно будет обернуть карту с помощью оболочки Collections.synchronizedMap
и использовать ее последовательно. На практике это противоречит цели использования ConcurrentHashMap
.
Дополнительный вопрос:
Так что потенциально может быть бесконечный цикл очистки, верно? Если другой поток продолжает добавлять элемент, размер карты всегда> 0, то поток, который пытается очистить, будет продолжать работать.
Неа. Там не будет бесконечного цикла. Метод clear()
не учитывает размер карты.
На самом деле произойдет то, что вызов clear()
вернется, и карта не обязательно будет пустой.
1 - Внимательно прочитав, я понял, что цитируемый javadoc не дает прямого ответа на вопрос. На самом деле, если вы посмотрите на «контракт» в Map.clear()
javadoc, то там будет там , что после возврата вызова карта будет пустой. Это явно противоречит Javadoc для ConcurrentHashMap.clear()
Javadoc, и явно противоречит тому, что на самом деле делает код.