Как сказал bkail, когда GC "удаляет" запись из WeakHashMap
, это не приведет к одновременной модификации. В действительности, GC собирает лежащий в основе объект, поскольку существует жесткая ссылка на сам объект WeakReference
(который содержит реальный ключ). Поэтому реальный объект (эталонный объект), на который непосредственно ссылается карта, не собирается, поэтому карта не изменяется до тех пор, пока один из ваших потоков не вызовет метод на этой карте. В это время карта проверяет эталонную очередь из ГХ и находит все ключи, которые были собраны, и удаляет их с карты - поэтому фактические изменения в структуре карты происходят в одном из ваших потоков.
Если подумать об этом, то может быть один случай, когда вы можете получить параллельную модификацию в такой карте, которую вы не получите в карте другого типа - если вы поместите ключ, который уже существует, или вызовете метод получения. Но на самом деле в параллельном приложении вы должны в любом случае блокировать эти вызовы, чтобы в вашей программе была действительно одновременная ошибка доступа.
Как говорится в ответе на ваш вопрос, вы действительно не должны использовать WeakHashMap
для кэша (даже если вы говорили о ключах кэширования). В кеше вы не хотите, чтобы ваши значения «магически» исчезали, когда на значения больше нет ссылок. Обычно вы хотите, чтобы они исчезали, когда существует определенное максимальное число (что-то вроде коллекций Apache LRUMap
) или освобождается по требованию памяти.
В дальнейшем вы можете использовать карту с SoftReference
(коллекции Apache предоставляют ReferenceMap
, который позволяет вам указать тип ссылки для ключа или значения). Мягкая ссылка указывается, чтобы быть выпущенной только на основе давления памяти - слабая ссылка, с другой стороны, должна делать больше с GC, признающим, что нет жесткой ссылки, остающейся к объекту, и может освободить ее в любое время. Конечно, то, как мягкая ссылка действительно работает, также зависит от реализации JVM.
РЕДАКТИРОВАТЬ : Я перечитал ваш вопрос и хочу затронуть еще один момент. Поскольку фактические изменения происходят с внутренними структурами WeakHashMap
в вашем собственном потоке, , если вы используете эту карту только в одном потоке, вам не нужно синхронизировать какие-либо вызовы методов . Это поведение ничем не отличается от любого другого Map
.