ReadWriteLock für Leser-Schreiber-Szenarien
Verwenden Sie ReadWriteLock, um gleichzeitige Lesezugriffe zu ermöglichen und zugleich exklusive Schreibzugriffe in einem Cache sicherzustellen.
ReadWriteLock für Leser-Schreiber-Szenarien ist eine kostenlose Java Academy-Lektion auf CoddyKit. Dies ist Lektion 2 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Java Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Java Academy-Kurs umfasst insgesamt 4 Lektionen.
Das Leser-Schreiber-Problem
Mehrere Threads können gemeinsam genutzte Daten sicher gleichzeitig lesen. Das Schreiben erfordert jedoch exklusiven Zugriff — es darf keine gleichzeitigen Lese- oder Schreibzugriffe geben. Ein ReadWriteLock bildet dieses Modell ab: mehrere gleichzeitige Leser ODER ein exklusiver Schreiber.
import java.util.concurrent.locks.*;
ReadWriteLock rwLock = new ReentrantReadWriteLock();
Lock readLock = rwLock.readLock();
Lock writeLock = rwLock.writeLock();Lesesperre: Gemeinsamer Zugriff
Mehrere Threads können die Lesesperre gleichzeitig halten, solange kein Thread die Schreibsperre hält:
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();
}
}
}Schreibsperre: Exklusiver Zugriff
Zu jedem Zeitpunkt kann nur ein Thread die Schreibsperre halten. Während eines Schreibvorgangs werden alle Leser und anderen Schreiber blockiert:
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();
}
}
}Vollständiges Cache-Beispiel
Ein threadsicherer Cache, bei dem Lesezugriffe überwiegen und Schreibzugriffe selten sind:
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(); }
}
}Herabstufung von Sperren
ReadWriteLock unterstützt die Herabstufung von Sperren: Schreibsperre erwerben → Lesesperre erwerben → Schreibsperre freigeben. Dadurch kann ein Thread von einem exklusiven Schreibzugriff zu einem gemeinsamen Lesezugriff wechseln, ohne die Sperre vollständig freizugeben:
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();
}Lesesperren können nicht hochgestuft werden
Eine Hochstufung von Sperren (Lesen → Schreiben) wird NICHT unterstützt. Wenn ein Thread, der eine Lesesperre hält, versucht, die Schreibsperre zu erwerben, entsteht ein Deadlock, weil die Schreibsperre auf ALLE Leser wartet, einschließlich dieses Threads:
// DEADLOCK: Do NOT do this
lock.readLock().lock();
try {
lock.writeLock().lock(); // DEADLOCK — waits for readLock to release
} finally {
lock.readLock().unlock();
}Wann ReadWriteLock hilfreich ist
ReadWriteLock ist sinnvoll, wenn:
- Lesezugriffe deutlich häufiger als Schreibzugriffe sind
- Leseoperationen eine gewisse Zeit benötigen (z. B. komplexe Abfragen)
Die Leistung kann sich verschlechtern, wenn Schreibzugriffe häufig sind (die Schreibsperre blockiert alle Leser) oder wenn Operationen sehr schnell sind (Overhead durch zwei Sperrobjekte).
ReadWriteLock im Vergleich zu synchronized
synchronized/ReentrantLock → immer nur ein Thread gleichzeitig (auch gleichzeitige Leser werden blockiert).
ReadWriteLock → mehrere gleichzeitige Leser, ein exklusiver Schreiber. Besserer Lesedurchsatz in Szenarien mit überwiegend Lesezugriffen.
// 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(); }
}Überlegungen zur Leistung
Das Erwerben und Freigeben von zwei Sperrobjekten verursacht im Vergleich zu einer einzelnen Sperre zusätzlichen Overhead. Führen Sie ein Profiling durch, bevor Sie annehmen, dass ReadWriteLock schneller ist. In Szenarien mit überwiegend Lesezugriffen und langen Operationen ist der Vorteil deutlich. Bei schnellen, schreibintensiven Workloads kann eine einfache ReentrantLock schneller sein.
Alternative: ConcurrentHashMap
Für einfache Map-Operationen ist ConcurrentHashMap häufig schneller als eine Kombination aus HashMap und ReadWriteLock, da sie interne Sperren auf Segmentebene ohne globale Konkurrenz verwendet:
// 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-safeFairness von Lesesperren
ReentrantReadWriteLock ist standardmäßig nicht fair (Leser können Schreiber aushungern). Verwenden Sie den fairen Konstruktor, um das Aushungern von Schreibern zu verhindern:
// Fair: waiting writers are served before new readers
ReentrantReadWriteLock fairLock = new ReentrantReadWriteLock(true);
System.out.println(fairLock.isFair()); // trueKurzer Test
Was ist in einer Anwendung mit überwiegend Lesezugriffen der wichtigste Vorteil von ReadWriteLock gegenüber einer einfachen synchronized-Methode?
Zusammenfassung: ReadWriteLock
Wichtige Erkenntnisse:
- Mehrere gleichzeitige Lesezugriffe ODER ein exklusiver Schreibzugriff — nicht beides
- readLock.lock()/unlock() für gemeinsame Lesezugriffe
- writeLock.lock()/unlock() für exklusive Schreibzugriffe
- Die Herabstufung von Sperren wird unterstützt; eine Hochstufung (Lesen→Schreiben) verursacht einen Deadlock
- Am besten geeignet für leseintensive Szenarien mit nichttrivialen Operationen; ConcurrentHashMap für einfache Maps
Häufig gestellte Fragen
Ist die Lektion „ReadWriteLock für Leser-Schreiber-Szenarien“ kostenlos?
Ja — der vollständige Text von „ReadWriteLock für Leser-Schreiber-Szenarien“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Java Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Java Academy-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „ReadWriteLock für Leser-Schreiber-Szenarien“?
Verwenden Sie ReadWriteLock, um gleichzeitige Lesezugriffe zu ermöglichen und zugleich exklusive Schreibzugriffe in einem Cache sicherzustellen. Du übst Java Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Java Academy zu starten?
Keine Vorkenntnisse erforderlich. Java Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 2 von 4.
Wie lange dauert die Lektion „ReadWriteLock für Leser-Schreiber-Szenarien“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Java Academy-Lektion Code schreiben und ausführen?
Ja. Jede Java Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- ReentrantLock vs. synchronized
- ReadWriteLock für Leser-Schreiber-Szenarien
- Atomare Variablen: Aktualisierungen ohne Locks
- StampedLock und optimistische Lesezugriffe