thread synchronizedmap safe current concurrent java collections concurrency hashmap

java - synchronizedmap - ¿Cómo funciona ConcurrentHashMap internamente?



thread safe hashmap (5)

El ConcurrentHashMap es muy similar a la clase java.util.HashTable , excepto que ConcurrentHashMap ofrece una mejor concurrencia que HashTable o synchronizedMap . ConcurrentHashMap no bloquea el mapa mientras está leyendo de él. Además, ConcurrentHashMap no bloquea todo el Map cuando escribe en él. Solo bloquea la parte del Map que se escribe, internamente.

Otra diferencia es que ConcurrentHashMap no lanza ConcurrentModificationException si ConcurrentHashMap se modifica mientras se itera. El Iterator no está diseñado para ser utilizado por más de un hilo, mientras que synchronizedMap puede arrojar ConcurrentModificationException

Estaba leyendo la documentación oficial de Oracle sobre Simultaneidad en Java y me preguntaba cuál podría ser la diferencia entre una Collection devuelta por

public static <T> Collection<T> synchronizedCollection(Collection<T> c);

y utilizando, por ejemplo, un

ConcurrentHashMap . Supongo que utilizo synchronizedCollection(Collection<T> c) en un HashMap . Sé que, en general, una colección sincronizada es esencialmente solo un decorador para mi HashMap por lo que es obvio que un ConcurrentHashMap tiene algo diferente en sus partes internas. ¿Tiene alguna información sobre esos detalles de implementación?

Editar: me di cuenta de que el código fuente está disponible públicamente: ConcurrentHashMap.java


Este es el artículo que me ayudó a entenderlo. Por qué ConcurrentHashMap es mejor que Hashtable y tan bueno como un HashMap.

Hashtable ofrece acceso concurrente a sus entradas, con una pequeña advertencia, todo el mapa está bloqueado para realizar cualquier tipo de operación. Si bien esta carga general no se puede utilizar en una aplicación web bajo carga normal, con cargas pesadas puede ocasionar retrasos en los tiempos de respuesta y sobrecarga de su servidor sin una buena razón.

Aquí es donde interviene ConcurrentHashMap. Ofrecen todas las características de Hashtable con un rendimiento casi tan bueno como un HashMap. ConcurrentHashMap lo logra mediante un mecanismo muy simple. En lugar de un bloqueo de mapa completo, la colección mantiene una lista de 16 bloqueos por defecto, cada uno de los cuales se usa para proteger (o bloquear) un solo cubo del mapa. Esto significa que 16 subprocesos pueden modificar la colección de una sola vez (siempre y cuando todos funcionen en diferentes intervalos). De hecho, esta colección no realiza ninguna operación que bloquee todo el mapa. El nivel de concurrencia de la colección, el número de subprocesos que pueden modificarlo al mismo tiempo sin bloquear, puede aumentarse. Sin embargo, un número más alto significa más sobrecarga de mantenimiento de esta lista de bloqueos.


Leería la ConcurrentHashMap.java ya que es bastante complicado en los detalles. En resumen, tiene

  • Múltiples particiones que se pueden bloquear de forma independiente. (16 por defecto)
  • Usar operaciones de bloqueos simultáneos para seguridad de hilos en lugar de sincronizados.
  • Tiene iteradores seguros para hilos. Los iteradores de synchronizedCollection no son seguros para subprocesos.
  • No expone los bloqueos internos. synchronizedCollection sí.

Los "problemas de escalabilidad" para Hashtable están presentes exactamente de la misma manera en Collections.synchronizedMap(Map) : usan una sincronización muy simple, lo que significa que solo un hilo puede acceder al mapa al mismo tiempo.

Esto no es un gran problema cuando tienes insertos y búsquedas simples (a menos que lo hagas de manera extremadamente intensiva), pero se convierte en un gran problema cuando necesitas recorrer todo el mapa, lo que puede llevar mucho tiempo para un mapa grande, mientras un hilo hace eso, todos los demás tienen que esperar si quieren insertar o buscar algo.

El ConcurrentHashMap utiliza técnicas muy sofisticadas para reducir la necesidad de sincronización y permitir el acceso de lectura paralelo por varios hilos sin sincronización y, lo que es más importante, proporciona un Iterador que no requiere sincronización e incluso permite que el Mapa se modifique durante la interacción (aunque no ofrece garantías si se devolverán o no los elementos que se insertaron durante la iteración).


Returned por synchronizedCollection () es un objeto cuyos métodos están sincronizados en este , por lo que todas las operaciones concurrentes en dicho contenedor se serializan. ConcurrentHashMap es un contenedor realmente concurrente con bloqueo de grano fino optimizado para mantener la contención lo más baja posible. Eche un vistazo al código fuente y verá lo que contiene.