synchronisiert und wieder eingetragen
Bei der Programmierung mit mehreren Threads verwenden wir Sperren, wenn der Code synchronisiert werden muss. Java bietet uns zwei Synchronisationsmethoden: eingebaute Schloss (synchronisiert) und explizites Lock (Reentrantlock). Explizite Schlösser wurden von JDK1.5 eingeführt. Was sind die Ähnlichkeiten und Unterschiede zwischen diesen beiden Schlössern? Ist es nur eine Option oder gibt es einen anderen Grund? Dieser Artikel wird für Sie herausfinden.
// Beispiel für synchronisierte Schlüsselwortverbrauch öffentlich synchronisierte void add (int t) {// synchronisierte Methode this.v += t;} public static synchronisierte void sub (int t) {// Synchronisierte statische Methodenwert -= t;} public int Decrementandget () {synchronisierte (OBJ) {// synchronisierte Code -Block -Return -V; }}Hier geht es darum, integrierte Schlösser zu verwenden. Sie haben es gelernt.
Das integrierte Schloss ist sehr bequem zu bedienen und erfordert keine explizite Erfassung und Freigabe. Jedes Objekt kann als integriertes Schloss verwendet werden. Mit integrierten Schlössern kann die meisten Synchronisationsszenarien gelöst werden. "Jedes Objekt kann als integriertes Schloss verwendet werden" bedeutet auch, dass das synchronisierte Schlüsselwort ein Objekt zugeordnet ist. Speziell:
Bei synchronisierten Akten auf die normale Methode ist das Schlossobjekt dies;
Bei synchronisierten Akten auf die statische Methode ist das Schleusenobjekt das Klassenobjekt der aktuellen Klasse.
Bei synchronisierten Akten im Codeblock ist das Sperrobjekt dieses OBJ in synchronisiertem (OBJ).
Explizite Schloss
Das eingebaute Schloss ist so einfach zu bedienen. Warum benötigen Sie ein explizites Schloss? Weil einige Dinge nicht mit eingebauten Schlössern durchgeführt werden können, wie zum Beispiel:
Wir möchten dem Schloss eine Wartezeit hinzufügen und aufgeben, bevor die Zeitüberschreitung erreicht wurde, damit wir nicht unendlich warten.
Wir möchten das Schloss unterbrochen erwerben, so dass der externe Faden uns ein Interrupt -Signal sendet und den Gewinde auf das Schloss rufen kann.
Wir möchten mehrere wartende Warteschlangen für Schlösser wie eine Produzentenwarteschlange und eine Konsumentenwarteschlange beibehalten und gleichzeitig die Effizienz von Schlösser verbessern.
Explizite Schlösser (Wiedereintrittsschläge) werden offiziell geboren, um diese flexiblen Bedürfnisse zu lösen. Reentrantlock bedeutet buchstäblich das Wiedereintrittschloss, und Wiedereintritt bedeutet, dass der Thread das gleiche Schloss mehrmals gleichzeitig anfordern kann, ohne dass er von selbst abgestimmt wird. Hier ist der Unterschied zwischen einem eingebauten Schloss und einem expliziten Schloss:
Timable: Renentrantlock.trylock (langfristig, Zeiteinheit) bietet eine Möglichkeit, die Wartezeit zu beenden. Wenn der Thread die Sperre in der angegebenen Zeit nicht erhält, gibt die Methode false zurück und beendet den Warten des Threads.
Interruptible: Sie müssen InterruptedException gesehen haben. Viele Multi-Thread-Methoden machen diese Ausnahme. Diese Ausnahme ist keine Belastung, die durch einen Defekt verursacht wird, sondern eine Notwendigkeit oder eine gute Sache. Die Interpretibilität bietet uns eine Möglichkeit, einen Thread früh zu beenden (anstatt bis zur enden der Thread-Ausführung zu warten), was für zeitaufwändige Aufgaben sehr nützlich ist. Bei eingebauten Schlössern wartet der Faden auf das eingebaute Schloss, wenn er es nicht erhalten kann. Es gibt keinen anderen Weg, um das Warten zu beenden, außer um das Schloss zu erwerben. Renentrantlock.lockinterruptisle () gibt uns einen Weg, das Warten mit einem Interrupt zu beenden.
CONDITION-Warteschlange: Nachdem ein Thread ein Schloss erfasst hat, kann es in einen Wartezustand eintreten, da es darauf wartet, dass eine bestimmte Bedingung auftritt (das integrierte Schloss durchläuft das Objekt. Der Thread, der in den Wartezustand eintritt, hängt und löst automatisch das Schloss ab, und diese Threads werden in die Bedingungswarteschlange gestellt. Synchronisiert hat nur eine bedingte Warteschlange, während Reentrantlock mehrere bedingte Warteschlangen haben kann. Was sind die Vorteile mehrerer Warteschlangen? Bitte lesen Sie auf.
Bedingte Prädikat: Nachdem ein Faden ein Schloss erlangt hat, muss es manchmal warten, bis eine bestimmte Erkrankung erfüllt wird, bevor er Dinge tun kann. Zum Beispiel muss der Produzent warten, bis der Cache nicht zufrieden ist, bevor er Nachrichten in die Warteschlange einfügen kann, während der Verbraucher warten muss, bis der Cache nicht leer ist, bevor er Nachrichten aus der Warteschlange abrufen kann. Diese Bedingungen werden als bedingte Prädikate bezeichnet. Der Faden muss zuerst das Schloss erwerben und dann bestimmen, ob das bedingte Prädikat erfüllt ist. Wenn es nicht zufrieden ist, wird es nicht nach unten ausgeführt. Der entsprechende Thread gibt die Ausführung rechts auf und löst die Sperre automatisch frei. Verschiedene Themen, die das gleiche Schloss unter Verwendung desselben Schlosses haben, können unterschiedliche bedingte Prädikate aufweisen. Wenn es nur eine bedingte Warteschlange gibt, ist es unmöglich zu bestimmen, welcher Thread in der bedingten Warteschlange zum Aufwachen ist, wenn ein bedingtes Prädikat erfüllt ist. Wenn jedoch jedes bedingte Prädikat eine separate bedingte Warteschlange aufweist, wissen wir, wenn eine Bedingung erfüllt ist, dass der Faden in der entsprechenden Warteschlange erweckt werden sollte (die integrierte Schloss wird durch das Objekt geweckt. Dies ist der Vorteil mehrerer bedingter Warteschlangen.
Bei der Verwendung integrierter Schlösser ist das Objekt selbst sowohl eine Schloss als auch eine bedingte Warteschlange. Bei der Verwendung expliziter Schlösser ist das Objekt von Renentrantlock ein Schloss, und die bedingte Warteschlange wird durch die Methode Renentrantlock.newCondition () erhalten. Mehrere bedingte Warteschlangen können durch Aufrufen dieser Methode mehrmals erhalten werden.
Ein typisches Beispiel für die Verwendung eines expliziten Schlosses ist wie folgt:
// Beispiel für die Verwendung von explizitem Lock Reentrantlock Lock = new Reentrantlock (); // Erwerben Sie das Schloss, dies ist die Verwendung, die dem synchronisierten Schlüsselwort entspricht. lock.lock (); try {// dein Code} endlich {lock.unlock ();} // Sie können Zeit und geben Sie das Schloss auf, wenn Sie die Sperre erhalten, nachdem die angegebene Zeit überschritten wurde. try {lock.rylock (10, TimeUnit.Seconds); Versuchen Sie {// Ihren Code} endlich {lock.unlock (); }} catch (InterruptedException E1) {// Ausnahmebehandlung} // Sie können unterbrechen, und der Thread -Thread kann unterbrochen werden, während Sie darauf warten, dass das Schloss erfasst wird, try {lock.lockinterriptable (); Versuchen Sie {// Ihren Code} endlich {lock.unlock (); }} catch (InterruptedException E) {// Ausnahmehandling} // Mehrere Warteschlangen finden Sie in [ArrayBlockingQueue] (https://github.com/carpenterlee/jcrecopes/blob/master/markdown/ArrayBlocke.md). zum Warten setzt */private endgültige Bedingung Notfull = lock.newCondition ();Beachten Sie, dass der obige Code Unlock () in einem endgültigen Block platziert, was erforderlich ist. Ein explizites Schloss wird nicht automatisch wie ein integriertes Schloss veröffentlicht. Bei der Verwendung eines expliziten Schlosses muss es manuell im endgültigen Block freigegeben werden. Wenn das Schloss aufgrund einer Ausnahme nach dem Erwerb des Schlosses nicht veröffentlicht wird, wird das Schloss nie veröffentlicht! Stellen Sie Unlock () in schließlich Block ein, um sicherzustellen, dass es normal freigegeben werden kann, egal was passiert.
abschließend
Integrierte Schlösser können die meisten Szenarien lösen, die eine Synchronisation erfordern. Nur wenn zusätzliche Flexibilität erforderlich ist, müssen explizite Schlösser in Betracht gezogen werden, wie z. B. Timing, unterbrechungsfrei und mehrere Warteschlangen.
Obwohl explizite Schlösser flexibel sind, erfordern sie eine explizite Anwendung und Freigabe, und die Freigabe muss in den endgültigen Block platziert werden, andernfalls kann das Schloss aufgrund von Ausnahmen nie freigegeben werden! Dies ist der offensichtlichste Nachteil der expliziten Sperren.
Zusammenfassend lassen Sie sich bei der Synchronisierung sicherer und einfacher zu verwenden, um implizite Schlösser zu verwenden.