Um Java -Parallelitätsprogramme zu lernen, müssen wir etwas über das Paket von Java.util.Concurrent kennenlernen. Es gibt viele Unterrichts -Toolklassen, die wir unter diesem Paket häufig verwenden, wie z. In der Java -Concurrency -Serie habe ich zum ersten Mal die Abstractqueuedsynchronizer -Klasse analysiert. Da diese Klasse wichtiger ist und der Code relativ lang ist, um sie so gründlich wie möglich zu analysieren, habe ich beschlossen, vier Artikel zu verwenden, um eine relativ vollständige Einführung in diese Klasse zu geben. Dieser Artikel ist eine zusammenfassende Einführung, um den Lesern ein vorläufiges Verständnis dieser Kategorie zu vermitteln. Für die Einfachheit der Erzählung werden einige Orte AQs verwenden, um diese Klasse in Zukunft darzustellen.
1. Wofür ist die Abstractqueuedsynchronizer -Klasse?
Ich glaube, dass viele Leser Reentrantlock verwendet haben, aber sie kennen die Existenz von Abstractqueuedsynchronizer nicht. Tatsächlich implementiert Reentrantlock eine interne Klassensynchronisation, die Abstractqueedsynchronizer erbt. Alle Implementierungen des Sperrmechanismus beruhen auf Sync -internen Klassen. Es kann auch gesagt werden, dass die Implementierung von Reentrantlock von der Abstractqueuedsynchronizer -Klasse abhängt. In ähnlicher Weise verwenden Countdownlatch-, CyclicBarrier- und Semaphor -Klassen auch die gleiche Methode, um ihre eigene Kontrolle über Schlösser zu implementieren. Es ist zu sehen, dass Abstractqueuedsynchronizer der Eckpfeiler dieser Klassen ist. Was genau wird in AQs implementiert, damit all diese Klassen davon abhängen? Es kann gesagt werden, dass AQS Infrastruktur für diese Klassen liefert, dh eine Passwortsperrung. Nachdem diese Klassen eine Passwortsperrung haben, können sie das Passwort der Passwortsperrung selbst festlegen. Darüber hinaus bietet AQS auch einen Warteschlangenbereich und einen Fadenlehrer. Wir wissen, dass Fäden wie ein primitiver Barbar sind. Sie wissen nicht, wie sie höflich sein sollen. Sie werden nur herumstürmen, also müssen Sie es Schritt für Schritt unterrichten, es sagen, wann es sich anstellen muss, wo Sie sich anstellen müssen, was zu tun ist, bevor Sie sich anstellen müssen und was nach der Warteschlange zu tun ist. Alle diese Bildungsarbeiten werden von AQS für Sie abgeschlossen. Die daraus ergebenden Themen sind sehr zivilisiert und höflich geworden und sind keine primitiven Barbaren mehr. In Zukunft müssen wir uns also nur mit diesen zivilisierten Themen auseinandersetzen. Nie zu viel Kontakt mit den ursprünglichen Threads!
2. Warum liefert Abstractqueedsynchronizer eine Passwortsperrung?
// Der Kopfknoten der Synchronisation Warteschlange Private Transient Volatile Node Head; // Der Schwanzknoten der Synchronisation Queue Private Transient Vosenknoten Schwanz; // Der private volatile Int -Zustand; // Synchronisierungszustand geschützt endgled GetState () {return stata;} // Set Synchronization State geschütztes void void setState (IND Newstate) {State =} Intgronisierungsstatus festgelegt) setze synchronisierungsstatus. {return unafe.comPareAndswapint (this, stateOffset, erwarten, update);}Der obige Code listet alle Mitgliedsvariablen von AQs auf. Sie können sehen, dass es nur drei Mitgliedsvariablen von AQs gibt, nämlich die Referenz zur Synchronisationskontrolle, die Synchronisation -Warteschlangen -Heckknotenreferenz und den Synchronisationszustand. Beachten Sie, dass alle drei Mitgliedsvariablen mit dem volatilen Schlüsselwort modifiziert werden, wodurch sichergestellt wird, dass mehrere Threads geändert werden. Der Kern der gesamten Klasse ist dieser Synchronisationszustand. Sie können sehen, dass der Synchronisationszustand tatsächlich eine INT-Variable ist. Sie können diesen Synchronisationsstatus als Passwortsperrung betrachten, und es handelt sich auch um eine vom Raum gesperrte Passwortsperrung. Der spezifische Wert des Status entspricht dem Passwort, das das Öffnen und Schließen der Passwortsperrung steuert. Natürlich wird das Passwort dieser Sperre von jeder Unterklasse bestimmt. Zum Beispiel bedeutet in Reentrantlock, dass der Zustand gleich 0 bedeutet, dass das Schloss offen ist, der Zustand größer als 0 bedeutet, dass das Schloss gesperrt ist, und im Semaphor ist der Zustand größer als 0, dass das Schloss geöffnet ist und der Zustand gleich 0 bedeutet, dass die Schloss gesperrt ist.
3. Wie wird der Warteschlangenbereich von Abstractquedsynchronizer implementiert?
Es gibt tatsächlich zwei Warteschlangenbereiche innerhalb von Abstractqueedsynchronizer, eine ist eine synchrone Warteschlange und die andere ist eine bedingte Warteschlange. Wie aus der obigen Abbildung ersichtlich ist, gibt es nur eine Synchronisationswarteschlange, während es mehrere Zustandswarteschlangen geben kann. Die Knoten der synchronen Warteschlange halten Verweise auf die vorderen und hinteren Knoten, während die Knoten der bedingten Warteschlange nur einen Verweis auf den Nachfolgerknoten haben. In der Abbildung repräsentiert T einen Faden. Jeder Knoten enthält einen Faden. Nachdem der Thread das Schloss nicht erfasst hat, tritt zuerst die Synchronisationswarteschlange in die Warteschlange ein. Wenn Sie die bedingte Warteschlange eingeben möchten, muss der Thread das Schloss enthalten. Schauen wir uns als nächstes die Struktur jedes Knotens in der Warteschlange an.
// Die Knoten der synchronen Warteschlange sind statischer endgültiger Klassenknoten {statischer endgültiger Knoten Shared = new node (); // Der aktuelle Thread hält die Sperre im Shared -Modus statischen endgültigen Knoten exklusiv = null; // Der aktuelle Thread hält die Sperre im exklusiven Modus statische endgültige int storniert = 1; // Der aktuelle Knoten hat das statische Final int Signal = -1 abgebrochen; // Die Fäden des Nachfolgeknotens müssen statische endgültige int -Bedingung = -2 ausführen; // Der aktuelle Knoten ist in der bedingten Warteschlange statische endgültige Int -Propagate = -3 in der Warteschlange; // Der nachfolgende Knoten kann den flüchtigen Lock -int -Waitus -Waitus direkt erwerben. // Bezeichnen Sie den Wartezustand des Stromknotens Flüchtigen Knoten vor; // den Vorwärtsknoten im synchronisierenden Warteschlangenknoten als nächstes bezeichnen; // den Nachfolgerknoten in der synchronisierenden Warteschlange zum flüchtigen Gewinde bezeichnen; // Der vom aktuelle Knoten gehaltene Thread bezieht sich auf den Knoten NextWaiter; // Bezeichnung des Nachfolgerknotens in der bedingten Warteschlange // ist der aktuelle Knotenstatus im Shared -Modus Final Boolean isShared () {return NextWaiter == Shared; } // den Vorwärtsknoten des aktuellen Knotens Final Node Vorgänger () zurückgeben () nullPointerexception {Knoten p = prev; if (p == null) {werfen neu nullPointerexception (); } else {return p; }} // Constructor 1 node () {} // Konstruktor 2, dieser Konstruktor wird standardmäßig mit dem Standardknoten (Thread -Thread, Knotenmodus) {// Beachten, dass der Haltemodus NextWaiter this.NextWaiter = Modus zugewiesen ist; this.thread = thread; } // Konstruktor 3, nur Knoten (Thread -Thread, int WaitStatus) wird in der Bedingungswarteschlange verwendet. this.thread = thread; }}Der Knoten stellt einen Knoten in der Synchronisationswarteschlange und der bedingten Warteschlange dar. Es ist eine innere Klasse von AbstractQueuedsynchronizer. Der Knoten verfügt über viele Attribute, wie Holding-Modus, Wartezustand, Vorsequenz und Nachfolger in synchronen Warteschlangen und Nachfolgerreferenzen in bedingten Warteschlangen usw. Die Synchronisations-Warteschlange und -bedingungswarteschlange können als Warteschlangenbereich angesehen werden, und jeder Knoten wird als Sitz in der Warteschlange angesehen, und der Thread wird als eine Kundestote. Wenn die Gäste zum ersten Mal kommen, klopfen sie an die Tür, um zu sehen, ob das Schloss geöffnet ist. Wenn das Schloss nicht geöffnet ist, gehen sie in den Warteschlangenbereich, um eine Zahlenplatte zu sammeln, zu erklären, wie sie das Schloss halten möchten, und schließlich am Ende der Warteschlange auf die Schlange.
4Wie, um den exklusiven Modus und den Freigabemodus zu verstehen?
Wie bereits erwähnt, erhält jeder Gast eine Zahlenplatte, bevor er anstehen und erklärt, dass er das Schloss besitzen möchte. Die Art und Weise, die Sperre zu besitzen, ist in den exklusiven Modus und den Freigabemodus unterteilt. Wie verstehen Sie also den exklusiven Modus und den Freigabemodus? Ich kann wirklich keine gute Analogie finden. Sie können sich eine öffentliche Toilette vorstellen. Menschen mit exklusiverem Modus sind dominierter. Ich gehe entweder nicht rein. Wenn ich reinkomme, erlaube ich nicht anderen, hineinzugehen. Ich besuche die gesamte Toilette alleine. Personen im Freigabemodus sind nicht so speziell. Wenn sie feststellen, dass die Toilette bereits verwendbar ist, zählt sie nicht, wenn sie von selbst hereinkommt. Sie müssen auch begeistert die Menschen hinterfragen, ob es ihnen etwas ausmacht, es zusammen zu benutzen. Wenn es den Menschen, die dahinter stören, es nichts ausmacht, es zusammen zu benutzen, müssen Sie sich nicht anstellen. Jeder wird zusammen gehen. Wenn die Menschen hinter ihnen verdienen, müssen sie natürlich in der Warteschlange bleiben und weiterhin Warteschlangen anwenden.
5 Wie kann man den Wartezustand eines Knotens verstehen?
Wir sehen auch, dass jeder Knoten einen Wartezustand hat, der in vier Staaten unterteilt ist: Storniert, Signal, Zustand und sich ausbreiten. Dieser Wartezustand kann als Schild angesehen werden, das neben dem Sitz hängt und den Wartezustand der Person auf dem aktuellen Sitz identifiziert. Der Status dieser Marke kann nicht nur selbst geändert werden, sondern auch andere können sie ändern. Wenn dieser Thread beispielsweise bereits während der Warteschlange aufgeben geplant hat, wird das Schild auf seinem Sitz auf Stornierung gesetzt, damit andere es aus der Warteschlange räumen können, wenn sie es sehen. Eine andere Situation ist, dass, wenn der Faden im Sitz im Sitz einschläft, befürchtet, dass er verschlafen wird, sodass er das Schild in der vorderen Position in die Signalposition ändert, da jeder zu seinen Sitzen zurückkehrt, bevor er die Warteschlange verlässt, um einen Blick darauf zu werfen. Wenn der Status auf dem Schild Signal ist, weckt er die nächste Person. Nur indem sie sicherstellen, dass die Marke in der vorderen Position Signal ist, schläft der aktuelle Faden friedlich. Der Zustandsstatus zeigt an, dass der Thread in der bedingten Warteschlange in die Warteschlange gestellt wird. Der Propagatstatus erinnert die nachfolgenden Threads daran, das Schloss direkt zu erwerben. Dieser Status wird nur im gemeinsamen Modus verwendet und später besprochen, wenn sie separat über den gemeinsam genutzten Modus sprechen.
6. Welche Operationen werden ausgeführt, wenn ein Knoten in die Synchronisationswarteschlange eintritt?
// Node Enqueue -Operation, kehren Sie zum vorherigen Knoten privaten Knoten eNQ (endgültiger Knotenknoten) {for (;;) {// den Verweis auf den Heckknoten des Synchronisations -Queue -Knotens T = Heck ab; // Wenn der Heckknoten leer ist, bedeutet dies, dass die Synchronisationswarteschlange nicht initialisiert wurde, wenn (t == null) {// die Synchronisationswarteschlange initialisieren if (vergleicheDead (neuer node ()) {Tail = Head; }} else {// 1. Zeigen Sie auf den aktuellen Heckknotenknoten.Prev = t; // 2. Stellen Sie den aktuellen Knoten auf den Heckknoten fest, wenn (vergleicheSettail (t, Knoten)) {// 3. Zeigen Sie den Nachfolger des alten Schwanzknotens auf den neuen Heckknoten t.Next = Knoten; // Der einzige Ausgang der für Schleife gibt t zurück; }}}}Beachten Sie, dass die Enqueue -Operation eine tote Schleife verwendet. Nur wenn der Knoten erfolgreich zum Schwanz der Synchronisationswarteschlange hinzugefügt wird, wird er zurückgegeben. Das Ergebnis ist der ursprüngliche Heckknoten der Synchronisationswarteschlange. Die folgende Abbildung zeigt den gesamten Betriebsprozess.
Die Leser müssen auf die Reihenfolge des Hinzufügens von Schwanzknoten achten, die in drei Schritte unterteilt sind: CAS zeigt auf Schwanzknoten, ändert die Heckknoten und zeigt die Nachfolger des alten Heckknotens auf den aktuellen Knoten. In einer gleichzeitigen Umgebung können diese drei Schritte nicht garantiert abgeschlossen werden. Daher wird bei der Funktionsweise der Löschen aller abgebrochenen Knoten in der Synchronisationswarteschlange, um Knoten in einem Nicht-Kanzlei-Zustand zu finden, nicht von vorne nach hinten, sondern von hinten nach vorne durchquert. Wenn jeder Knoten in die Warteschlange eintritt, beträgt sein Wartezustand 0. Nur wenn der Faden des nachfolgenden Knotens ausgesetzt werden muss, wird der Wartezustand des vorherigen Knotens in Signal geändert.
Hinweis: Alle oben genannten Analysen basieren auf JDK1.7, und es wird Unterschiede zwischen verschiedenen Versionen geben, die Leser müssen aufpassen.
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, es wird für das Lernen aller hilfreich sein und ich hoffe, jeder wird Wulin.com mehr unterstützen.