Не нужно спекулировать. source code for ConcurrentHashMap открыт, и любой может его прочитать. (Это JDK 8 build 128, первый кандидат на выпуск JDK 8.)
Вам не составит труда понять это, так как это всего лишь 6 300 строк. :-) Собственно, хорошая часть этого - комментарии, и большая часть кода идет на обработку крайних случаев. Прямые пути get() и put() не очень сложны и составляют всего несколько десятков строк кода.
Ваше понимание операций чтения (get(), contains()) верно; нет блокировки. Хеширование в ковше и поиск в ведре, если необходимо, просты, без блокировки. Наблюдение за памятью обеспечивается неустойчивыми чтениями. (На линиях 622-623 поля и next
являются неустойчивыми.) Операции чтения выполняются одновременно с другими считываниями, а также с записью в тот же ковш.
Политика удаления и замены значений довольно проста в том, что головка ковша заблокирована, когда ведро выполняется поиск и изменение. См. Блок synchronized
на линии 1117 от replaceNode
. A put
, который добавляет к существующему ковшу, аналогичен; см. блок synchronized
по строке 1027 от putVal
. Разумеется, эти операции блокируют другие потоки, пытающиеся удалить, заменить или добавить записи в это же ведро. Если значение находится в процессе замены, поток, получающий значение для этого ключа, будет видеть либо старое значение, либо новое значение, в зависимости от того, найдет ли поток чтения узел до или после того, как значение будет заменено записывать нить.
Существует специальный чехол для помещения первого элемента в ведро. На линиях 1018-1020, если putVal
находит ведро пустым, оно создаст новый узел и CAS (сравните и поменяйте) его на место. Если это будет выполнено, операция будет завершена. Если два потока пытаются добавить узлы в одно и то же ведро более или менее одновременно, CAS для первого будет успешным, а CAS для второго не удастся. Но учтите, что этот код находится внутри цикла for (строка 1014). Поток, CAS которого провалился, просто обходит цикл и повторяет попытку. Фактически все остальные операции записи находятся в цикле. Общий подход заключается в том, что операции идут оптимистично, но проверяются для одновременных авторов. Если попытка оптимизма не удалась, операция повторяется и проходит через (возможно) другой путь, основанный на обновленном состоянии.
Я думаю, вам придется подождать, пока вы не напишете на хэш-карту, поскольку вы можете прочитать, что добавляет поток. – OmniOwl
Если выполняется операция записи, все остальные потоки должны ждать. –