© Swill Klitch/Shutterstock.com
Upgraden von ReadWriteLock

Lock & Crete


Die Java-Klasse ReentrantReadWriteLock kann einen Read Lock nicht auf einen Write Lock upgraden. Kotlins Erweiterungsfunktion ReentrantReadWriteLock.write() schummelt ein wenig, indem sie den Read Lock vor dem Upgrade loslässt und so die Tür für Race Conditions öffnet. Eine bessere Lösung ist StampedLock, das über eine Methode verfügt, mit der versucht wird, den Lock in einen Write Lock umzuwandeln.

In Java 5 kam das ReadWriteLock-Interface mit einer Implementierung von ReentrantReadWriteLock. Sie hatte die sinnvolle Einschränkung, dass wir einen Write Lock zu einem Read Lock herabstufen, jedoch keinen Read Lock auf einen Write Lock upgraden konnten. Wenn wir es versuchten, bekamen wir sofort einen Deadlock. Der Grund für diese Einschränkung: Wenn zwei Threads einen Read Lock hätten, was würde geschehen, wenn beide gleichzeitig versuchten, ein Upgrade durchzuführen? Nur einer könnte erfolgreich sein – aber was ist mit dem anderen Thread? Um sicherzugehen, wird jeder Thread, der ein Upgrade versucht, konsequent blockiert.

Das Herabstufen der ReentrantReadWriteLock funktioniert gut, und wir können in diesem Fall gleichzeitig einen Read Lock und einen Write Lock halten. Eine Herabstufung bedeutet, dass wir, während wir einen Write Lock halten, auch den Read Lock sperren und dann den Write Lock freigeben. Das bedeutet, dass wir anderen Threads das Lesen, aber nicht das Schreiben gestatten (Listing 1).

Listing 1

import java.util.concurrent.locks.*; // This runs through fine public class DowngradeDemo { public static void main(String... args) { var rwlock = new ReentrantReadWriteLock(); System.out.println(rwlock); // w=0, r=0 rwlock.writeLock().lock(); System.out.println(rwlock); // w=1, r=0 rwlock.readLock().lock(); System.out.println(rwlock); // w=1, r=1 rwlock.writeLock().unlock();  // at this point other threads can also acquire read locks System.out.println(rwlock); // w=0, r=1 rwlock.readLock().unlock(); System.out.println(rwlock); // w=0, r=0 } }

Der Versuch, einen ReentrantReadWriteLock von Lesen auf Schreiben zu aktualisieren, führt zu einem Deadlock (Listing 2).

Listing 2

// This deadlocks public class UpgradeDemo { public static void main(String... args) { var rwlock = new ReentrantReadWriteLock(); System.out.println(rwlock); // w=0, r=0 rwlock.readLock().lock(); System.out.println(rwlock); // w=0, r=1 rwlock.writeLock().lock(); // deadlock System.out.println(rwlock); rwlock.readLock().unlock(); System.out.println(rwlock); rwlock.writeLock().unl...

Neugierig geworden?

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang