ReadWriteLock pour les scénarios lecteur-rédacteur
Utilisez ReadWriteLock pour autoriser les lectures simultanées tout en garantissant des écritures exclusives dans un cache.
ReadWriteLock pour les scénarios lecteur-rédacteur est une leçon Java Academy gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Java Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Java Academy comprend 4 leçons au total.
Le problème des lecteurs et des rédacteurs
Plusieurs fils d’exécution peuvent lire simultanément des données partagées en toute sécurité. En revanche, l’écriture nécessite un accès exclusif : aucune lecture ni écriture concurrente. Un ReadWriteLock modélise ce fonctionnement : plusieurs lecteurs concurrents OU un rédacteur exclusif.
import java.util.concurrent.locks.*;
ReadWriteLock rwLock = new ReentrantReadWriteLock();
Lock readLock = rwLock.readLock();
Lock writeLock = rwLock.writeLock();Verrou de lecture : accès partagé
Plusieurs fils d’exécution peuvent détenir simultanément le verrou de lecture tant qu’aucun fil ne détient le verrou d’écriture :
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();
}
}
}Verrou d’écriture : accès exclusif
Un seul fil d’exécution peut détenir le verrou d’écriture à la fois. Tous les lecteurs et les autres rédacteurs sont bloqués pendant une écriture :
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();
}
}
}Exemple complet de cache
Un cache sûr en environnement concurrent, où les lectures sont prédominantes et les écritures rares :
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(); }
}
}Déclassement du verrouillage
ReadWriteLock prend en charge le déclassement du verrouillage : acquérir le verrou d’écriture → acquérir le verrou de lecture → libérer le verrou d’écriture. Cela permet à un fil d’exécution de passer d’une écriture exclusive à une lecture partagée sans libérer le verrou :
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();
}Le verrou de lecture ne peut pas être renforcé
Le renforcement du verrouillage (lecture → écriture) n’est PAS pris en charge. Si un fil d’exécution détenant un verrou de lecture tente d’acquérir le verrou d’écriture, il provoque un interblocage, car le verrou d’écriture attend TOUS les lecteurs, y compris lui-même :
// DEADLOCK: Do NOT do this
lock.readLock().lock();
try {
lock.writeLock().lock(); // DEADLOCK — waits for readLock to release
} finally {
lock.readLock().unlock();
}Quand ReadWriteLock est utile
ReadWriteLock est avantageux lorsque :
- Les lectures sont nettement plus nombreuses que les écritures
- Les opérations de lecture prennent un temps non négligeable (par exemple, des requêtes complexes)
Il peut dégrader les performances lorsque les écritures sont fréquentes (le verrou d’écriture bloque tous les lecteurs) ou lorsque les opérations sont très rapides (coût de deux objets de verrouillage).
Comparaison de ReadWriteLock avec synchronized
synchronized/ReentrantLock → un seul fil d’exécution à la fois (même les lecteurs concurrents sont bloqués).
ReadWriteLock → plusieurs lecteurs concurrents et un rédacteur exclusif. Meilleur débit de lecture dans les scénarios dominés par les lectures.
// 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(); }
}Considérations liées aux performances
L’acquisition et la libération de deux objets de verrouillage ajoutent un coût par rapport à un verrou unique. Mesurez les performances avant de supposer que ReadWriteLock est plus rapide. Dans les scénarios dominés par les lectures et comportant des opérations longues, l’avantage est évident. Pour les charges rapides et dominées par les écritures, un simple ReentrantLock peut être plus rapide.
Alternative avec ConcurrentHashMap
Pour les opérations simples sur une table associative, ConcurrentHashMap est souvent plus rapide qu’une combinaison HashMap + ReadWriteLock, car il utilise des verrous internes au niveau des segments, sans contention globale :
// 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-safeÉquité du verrou de lecture
Par défaut, ReentrantReadWriteLock n’est pas équitable (les lecteurs peuvent affamer les rédacteurs). Utilisez le constructeur équitable pour éviter la famine des rédacteurs :
// Fair: waiting writers are served before new readers
ReentrantReadWriteLock fairLock = new ReentrantReadWriteLock(true);
System.out.println(fairLock.isFair()); // trueVérification rapide
Dans une application dominée par les lectures, quel est le principal avantage de ReadWriteLock par rapport à une simple méthode synchronized ?
Récapitulatif : ReadWriteLock
Points essentiels :
- Plusieurs lectures concurrentes OU une écriture exclusive — jamais les deux
- readLock.lock()/unlock() pour les lectures partagées
- writeLock.lock()/unlock() pour les écritures exclusives
- Le déclassement du verrouillage est pris en charge ; son renforcement (lecture→écriture) provoque un interblocage
- Idéal pour les charges dominées par les lectures avec des opérations non triviales ; utilisez ConcurrentHashMap pour les tables associatives simples
Questions Fréquemment Posées
La leçon « ReadWriteLock pour les scénarios lecteur-rédacteur » est-elle gratuite ?
Oui — le texte complet de « ReadWriteLock pour les scénarios lecteur-rédacteur » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Java Academy, passe à CoddyKit PRO. Le cours Java Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « ReadWriteLock pour les scénarios lecteur-rédacteur » ?
Utilisez ReadWriteLock pour autoriser les lectures simultanées tout en garantissant des écritures exclusives dans un cache. Tu pratiques Java Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Java Academy ?
Aucune expérience préalable n'est requise. Java Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.
Combien de temps prend la leçon « ReadWriteLock pour les scénarios lecteur-rédacteur » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Java Academy ?
Oui. Chaque leçon Java Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- ReentrantLock et synchronized
- ReadWriteLock pour les scénarios lecteur-rédacteur
- Variables atomiques : mises à jour sans verrou
- StampedLock et lectures optimistes