Usa ConcurrentHashMap. Bloquea por bin en vez de bloquear el mapa entero, con un compare and set para los bins vacíos y sincronizando sobre la cabeza del bin en el resto de casos, así que los lectores nunca se bloquean y las escrituras en bins distintos avanzan en paralelo. Un mapa sincronizado serializa cada operación sobre un único lock, y encima sigue necesitando sincronización externa al iterar. Usa sus métodos atómicos, como compute y merge, en lugar de un get seguido de un put.
Por qué lo preguntan los entrevistadores
Comprueba si sabes por qué existen las colecciones concurrentes en vez de tirar de synchronized por reflejo. El entrevistador quiere la diferencia de granularidad y el punto práctico crucial de que envolver un mapa no vuelve atómicas las secuencias de operaciones. Saber que el tamaño y la iteración son débilmente consistentes, y cuándo CopyOnWriteArrayList o una BlockingQueue son mejor herramienta, redondea la respuesta.
Cómo estructurar tu respuesta
- Nombra la herramienta primero, y luego el mecanismo que la hace rápida.
- Explica por qué un envoltorio sincronizado sigue sin bastar para acciones compuestas.
- Señala los métodos atómicos para leer, modificar y escribir.
- Menciona las demás colecciones concurrentes y cuándo encajan.
Ejemplo de respuesta
ConcurrentHashMap, casi siempre. La diferencia importante es la granularidad: bloquea al nivel de un solo bin, y una inserción en un bin vacío es solo un compare and set, así que las claves no relacionadas no compiten y las lecturas van sin lock. Un mapa sincronizado pone un único lock alrededor de todo, así que se convierte en el cuello de botella en cuanto hay varios hilos ocupados. La trampa mayor del envoltorio sincronizado es que las llamadas individuales son atómicas pero las secuencias no, así que si compruebo containsKey y luego hago put, otro hilo puede colarse en medio, y la iteración directamente no es segura si no sostengo yo el lock. Por eso uso los métodos atómicos: computeIfAbsent para una entrada de caché construida de forma perezosa, merge para contadores, de modo que la lectura, modificación y escritura ocurra dentro del mapa. Lo que hay que saber es que size es una estimación bajo modificación concurrente y que los iteradores son débilmente consistentes, así que no lanzan pero pueden no ver las escrituras más nuevas. Para otras formas uso CopyOnWriteArrayList cuando las lecturas superan de largo a las escrituras, y una BlockingQueue para el traspaso entre productor y consumidor.
¿Tienes esta entrevista a la vuelta de la esquina? GhostPilot escucha tu llamada en vivo, detecta la pregunta en cuanto la hacen y pone una respuesta estructurada en tu pantalla en tiempo real. Pruébalo en tu próxima entrevista de práctica, o coge un Session Pass de $29, sin suscripción, para la de verdad.
Mira cómo funcionaPreguntas de seguimiento que puedes esperar
- ¿Qué riesgos tiene hacer trabajo caro dentro de computeIfAbsent?
- ¿Qué significa en la práctica una iteración débilmente consistente?
- ¿Cuándo es CopyOnWriteArrayList la elección equivocada?
Más preguntas para Desarrollador Java
Tu entrevistador hará su propia versión de esta. Pega la descripción real del puesto en el Question Predictor gratuito y obtén las 20 preguntas que ese puesto tiene más probabilidades de hacerte, con lo que cada una busca en realidad.
Predecir mis preguntas