ReadWriteLock para escenarios de lectores y escritores
Use ReadWriteLock para permitir lecturas simultáneas y garantizar escrituras exclusivas en una caché.
ReadWriteLock para escenarios de lectores y escritores es una lección gratuita de Java Academy en CoddyKit. Esta es la lección 2 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Java Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Java Academy incluye 4 lecciones en total.
El problema de los lectores y escritores
Varios subprocesos pueden leer datos compartidos de forma segura al mismo tiempo. Sin embargo, escribir requiere acceso exclusivo: no puede haber lecturas ni escrituras simultáneas. Un ReadWriteLock modela este comportamiento: varios lectores simultáneos O un único escritor exclusivo.
import java.util.concurrent.locks.*;
ReadWriteLock rwLock = new ReentrantReadWriteLock();
Lock readLock = rwLock.readLock();
Lock writeLock = rwLock.writeLock();Bloqueo de lectura: acceso compartido
Varios subprocesos pueden mantener el bloqueo de lectura simultáneamente siempre que ningún subproceso mantenga el bloqueo de escritura:
class ReadableCache {
private final Map<String, String> cache = new HashMap<>();
private final ReadWriteLock lock = new ReentrantReadWriteLock();
String get(String key) {
lock.readLock().lock();
try {
return cache.get(key); // concurrent reads OK
} finally {
lock.readLock().unlock();
}
}
}Bloqueo de escritura: acceso exclusivo
Solo un subproceso puede mantener el bloqueo de escritura a la vez. Todos los lectores y los demás escritores quedan bloqueados durante una escritura:
class WritableCache extends ReadableCache {
private final ReadWriteLock wLock = new ReentrantReadWriteLock();
private final Map<String, String> data = new HashMap<>();
void put(String key, String value) {
wLock.writeLock().lock();
try {
data.put(key, value); // exclusive write
} finally {
wLock.writeLock().unlock();
}
}
}Ejemplo completo de caché
Una caché segura para subprocesos en la que predominan las lecturas y las escrituras son poco frecuentes:
class Cache<K,V> {
private final Map<K,V> map = new HashMap<>();
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
V get(K key) {
lock.readLock().lock();
try { return map.get(key); }
finally { lock.readLock().unlock(); }
}
void put(K key, V value) {
lock.writeLock().lock();
try { map.put(key, value); }
finally { lock.writeLock().unlock(); }
}
int size() {
lock.readLock().lock();
try { return map.size(); }
finally { lock.readLock().unlock(); }
}
}Degradación del bloqueo
ReadWriteLock admite la degradación del bloqueo: adquirir el bloqueo de escritura → adquirir el bloqueo de lectura → liberar el bloqueo de escritura. Esto permite que un subproceso pase de una escritura exclusiva a una lectura compartida sin liberar el bloqueo:
ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
Lock r = rwl.readLock(), w = rwl.writeLock();
w.lock(); // acquire write
try {
// modify data
r.lock(); // acquire read WHILE holding write
} finally {
w.unlock(); // release write, now holding read only
}
try {
// safely read the just-written data
} finally {
r.unlock();
}El bloqueo de lectura no se puede actualizar
La actualización del bloqueo (de lectura → escritura) NO es compatible. Si un subproceso que mantiene un bloqueo de lectura intenta adquirir el bloqueo de escritura, se produce un interbloqueo porque el bloqueo de escritura espera a TODOS los lectores, incluido él mismo:
// DEADLOCK: Do NOT do this
lock.readLock().lock();
try {
lock.writeLock().lock(); // DEADLOCK — waits for readLock to release
} finally {
lock.readLock().unlock();
}Cuándo resulta útil ReadWriteLock
ReadWriteLock resulta beneficioso cuando:
- Las lecturas superan ampliamente a las escrituras
- Las operaciones de lectura tardan un tiempo considerable (por ejemplo, consultas complejas)
Puede perjudicar el rendimiento cuando las escrituras son frecuentes (el bloqueo de escritura bloquea a todos los lectores) o cuando las operaciones son muy rápidas (por la sobrecarga de dos objetos de bloqueo).
Comparación entre ReadWriteLock y synchronized
synchronized/ReentrantLock → solo un subproceso a la vez (incluso las lecturas simultáneas quedan bloqueadas).
ReadWriteLock → varios lectores simultáneos y un escritor exclusivo. Ofrece un mejor rendimiento de lectura en situaciones con predominio de lecturas.
// synchronized: only one thread reads at a time
synchronized String get(String key) { return cache.get(key); }
// ReadWriteLock: many threads can read simultaneously
String get2(String key) {
lock.readLock().lock();
try { return cache.get(key); }
finally { lock.readLock().unlock(); }
}Consideraciones de rendimiento
Adquirir y liberar dos objetos de bloqueo añade sobrecarga frente a un único bloqueo. Perfile el código antes de suponer que ReadWriteLock es más rápido. En situaciones con predominio de lecturas y operaciones largas, el beneficio es claro. Para cargas de trabajo rápidas con predominio de escrituras, un ReentrantLock sencillo puede ser más rápido.
Alternativa: ConcurrentHashMap
Para operaciones sencillas con mapas, ConcurrentHashMap suele ser más rápido que un HashMap + ReadWriteLock, ya que utiliza bloqueos internos a nivel de segmento sin contención global:
// Often better than HashMap + ReadWriteLock for simple operations:
Map<String, String> concurrent = new ConcurrentHashMap<>();
concurrent.put("key", "value"); // thread-safe, no explicit lock
String v = concurrent.get("key"); // thread-safeEquidad del bloqueo de lectura
De forma predeterminada, ReentrantReadWriteLock no es equitativo (los lectores pueden provocar inanición de los escritores). Use el constructor equitativo para evitar la inanición de los escritores:
// Fair: waiting writers are served before new readers
ReentrantReadWriteLock fairLock = new ReentrantReadWriteLock(true);
System.out.println(fairLock.isFair()); // trueComprobación rápida
En una aplicación con predominio de lecturas, ¿cuál es la principal ventaja de ReadWriteLock frente a un método synchronized sencillo?
Resumen: ReadWriteLock
Conceptos clave:
- Varias lecturas simultáneas O una escritura exclusiva; no ambas
- readLock.lock()/unlock() para lecturas compartidas
- writeLock.lock()/unlock() para escrituras exclusivas
- Se admite la degradación del bloqueo; actualizarlo (de lectura → escritura) provoca un interbloqueo
- Es mejor para cargas con predominio de lecturas y operaciones considerables; use ConcurrentHashMap para mapas sencillos
Preguntas frecuentes
¿La lección «ReadWriteLock para escenarios de lectores y escritores» es gratis?
Sí — el texto completo de «ReadWriteLock para escenarios de lectores y escritores» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Java Academy, actualiza a CoddyKit PRO. El curso de Java Academy incluye 4 lecciones en total.
¿Qué aprenderé en «ReadWriteLock para escenarios de lectores y escritores»?
Use ReadWriteLock para permitir lecturas simultáneas y garantizar escrituras exclusivas en una caché. Practicas Java Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Java Academy?
No se requiere experiencia previa. Java Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 2 de 4.
¿Cuánto tiempo toma la lección «ReadWriteLock para escenarios de lectores y escritores»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Java Academy?
Sí. Cada lección de Java Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- ReentrantLock frente a synchronized
- ReadWriteLock para escenarios de lectores y escritores
- Variables atómicas: actualizaciones sin bloqueo
- StampedLock y lecturas optimistas