Vor Java 5.0 gab es nur synchronisierte (eingebaute Sperren) und flüchtige. Nach Java 5.0 wurde die Anzeigesperre ReentrantLock eingeführt.
ReentrantLock-Übersicht
ReentrantLock ist eine Wiedereintrittssperre. Sie unterscheidet sich von der integrierten Sperre. Sie erfordert bei jeder Verwendung eine explizite Sperre und Entsperrung und bietet erweiterte Funktionen: faire Sperre, zeitgesteuerte Sperre und abfragbare Sperre Die Sperre kann das Lebendigkeitsproblem von ReentrantLock-Implementierungen effektiv vermeiden
Schnittstelle sperren:
Kopieren Sie den Codecode wie folgt:
öffentliche Schnittstelle sperren {
//Blockieren, bis die Sperre erhalten oder unterbrochen wird
void lock();
// Blockieren, bis die Sperre erhalten wird oder beim Unterbrechen eine Ausnahme ausgelöst wird
void lockInterruptably() löst eine InterruptedException aus;
//Nur abrufen, wenn die Sperre verfügbar ist, andernfalls direkt zurückkehren
boolean tryLock();
// Erhalten Sie die Sperre nur, wenn sie innerhalb der angegebenen Zeit verfügbar ist, andernfalls kehren Sie direkt zurück und lösen bei Unterbrechung eine Ausnahme aus
boolean tryLock(long time, TimeUnit-Einheit) löst InterruptedException aus;
void unlock();
//Eine an diese Sperre gebundene Bedingung zurückgeben
Bedingung newCondition();
}
Verwendung sperren
Kopieren Sie den Codecode wie folgt:
Lock lock = new ReentrantLock();
lock.lock();
versuchen{
//Objektstatus aktualisieren
}Endlich{
//Beachten Sie hier, dass zum Entsperren ein finaler Codeblock vorhanden sein muss
// Andernfalls kann es leicht zu Deadlocks und anderen Aktivitätsproblemen kommen.
lock.unlock();
}
ReentrantLock-Funktionen
Abrufsperren und zeitgesteuerte Sperren
Abrufbare und zeitgesteuerte Sperranforderungen werden über die tryLock()-Methode implementiert, die sich vom bedingungslosen Erwerb von Sperren unterscheidet. Viele Fälle von Deadlocks werden durch sequentielle Sperren verursacht, und verschiedene Threads versuchen, sie zu erwerben Es blockiert beim Sperren und gibt die bereits gehaltene Sperre nicht frei, was schließlich zu einem Deadlock führt. Wenn die tryLock()-Methode versucht, eine Sperre zu erhalten, kehrt sie entsprechend der Einstellungsmethode sofort zurück, wenn sie bereits von einem anderen Thread gehalten wird, anstatt zu blockieren und zu warten. Gleichzeitig wird die Sperre freigegeben, die sie danach hält Sie können es entsprechend der Rückgabe zurückgeben. Als Ergebnis wird ein erneuter Versuch oder ein Abbruch durchgeführt, um einen Deadlock zu vermeiden.
Fairness
Der ReentrantLock-Konstruktor bietet zwei Optionen: faire Sperre und unfaire Sperre (Standard). Bei sogenannten fairen Sperren erhalten Threads Sperren in der Reihenfolge, in der sie Anfragen stellen, und das Springen in die Warteschlange ist nicht zulässig. Bei unfairen Sperren ist das Springen in die Warteschlange jedoch zulässig: Wenn ein Thread den Erwerb einer Sperre anfordert, sofern die Sperre verfügbar ist Dann überspringt dieser Thread den wartenden Thread in der Warteschlange und erhält die Sperre. Wir möchten generell, dass alle Sperren unfair sind. Denn bei der Durchführung von Sperrvorgängen wird die Leistung aufgrund der Fairness aufgrund des Mehraufwands für die Thread-Suspendierung und Thread-Wiederherstellung erheblich beeinträchtigt. Stellen Sie sich eine Situation vor: Thread A hält eine Sperre, Thread B fordert die Sperre an, sodass Thread B angehalten wird, wenn Thread A die Sperre aufhebt, sodass Thread B gleichzeitig versucht, die Sperre erneut zu erlangen C fordert auch den Erwerb dieser Sperre an, dann wird der C-Thread diese Sperre wahrscheinlich erwerben, verwenden und freigeben, bevor der B-Thread vollständig aktiviert ist. Dies ist eine Win-Win-Situation. Der Zeitpunkt, zu dem B die Sperre erhält (B kann die Sperre erst nach dem Aufwachen erwerben), wird nicht verzögert, und der Durchsatz wird ebenfalls verbessert. In den meisten Fällen ist die Leistung unfairer Sperren höher als die Leistung fairer Sperren.
Sperrenerfassungsvorgänge können unterbrochen werden
Die lockInterruptably-Methode erhält die Sperre und reagiert gleichzeitig auf Interrupts, sodass keine anderen Arten von unterbrechungsfreien Blockierungsvorgängen erstellt werden müssen.
ReadWriteLockReadWriteLock
ReentrantLock ist eine Standard-Mutex-Sperre. Es kann jeweils nur ein Thread die Sperre halten. Die Lese-/Schreibsperre ist unterschiedlich. Sie macht zwei Sperrobjekte verfügbar, von denen eines für Lesevorgänge und das andere für Schreibvorgänge verwendet wird.
Kopieren Sie den Codecode wie folgt:
öffentliche Schnittstelle ReadWriteLock {
/**
* Gibt die zum Lesen verwendete Sperre zurück.
*
* @return die zum Lesen verwendete Sperre.
*/
readLock(); sperren
/**
* Gibt die zum Schreiben verwendete Sperre zurück.
*
* @return die zum Schreiben verwendete Sperre.
*/
sperren writeLock();
}
Optionale Implementierung:
1. Freigabepriorität
2. Thread-Sprünge in der Zeile lesen
3. Wiedereintritt
4.Downgrade
5.Upgrade
ReentrantReadWriteLock implementiert die ReadWriteLock-Schnittstelle und der Konstruktor stellt zwei Erstellungsmethoden bereit: faire Sperre und unfaire Sperre. Lese-/Schreibsperren eignen sich für Situationen, in denen mehr gelesen und weniger geschrieben wird, und können eine bessere Parallelität erreichen.
Der Beispielkopiercode lautet wie folgt:
öffentliche Klasse ReadWriteMap<K, V> {
private Map<K, V>-Karte;
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private finale Sperre readLock = lock.readLock();
private finale Sperre writeLock = lock.writeLock();
public ReadWriteMap(Map<K, V> map) {
this.map = Karte;
}
public V get(K key) {
readLock.lock();
versuchen {
return map.get(key);
} Endlich {
readLock.unlock();
}
}
public void put(K key, V value) {
writeLock.lock();
versuchen {
map.put(key, value);
} Endlich {
writeLock.unlock();
}
}
}