Um eine Analogie zu verwenden: Ein Objekt ist wie ein großes Haus, die Tür steht immer offen. Es gibt viele Räume (auch Methoden genannt) in einem Haus. Diese Räume sind entweder verschlossen (synchronisierte Methode) oder entriegelt (normale Methode). An der Zimmertür befindet sich ein Schlüssel. Mit diesem Schlüssel können alle verschlossenen Räume geöffnet werden. Außerdem vergleiche ich alle Threads, die Methoden dieses Objekts aufrufen möchten, mit Personen, die einen bestimmten Raum in diesem Haus betreten möchten. Das ist alles. Werfen wir einen Blick darauf, wie diese Dinge miteinander funktionieren.
Hier klären wir zunächst unsere Voraussetzungen. Das Objekt verfügt über mindestens eine synchronisierte Methode, ansonsten hat dieser Schlüssel keine Bedeutung. Natürlich wird es bei uns kein solches Thema geben.
Eine Person möchte einen verschlossenen Raum betreten. Er kommt zur Tür des Hauses und sieht dort den Schlüssel (was anzeigt, dass noch niemand den verschlossenen Raum benutzen möchte). Also ging er hinauf, holte die Schlüssel und nutzte die Räume wie geplant. Bitte beachten Sie, dass er den Schlüssel nach jeder Nutzung des verschlossenen Zimmers unverzüglich zurückgibt. Auch wenn er zwei verschlossene Räume hintereinander nutzen möchte, muss er zwischendurch den Schlüssel abgeben und wieder zurückholen.
Daher lautet der Grundsatz bei der Verwendung von Schlüsseln unter normalen Umständen: „Leihen Sie sie aus, wenn Sie sie verwenden, und geben Sie sie zurück, sobald Sie sie verwenden.“
Zu diesem Zeitpunkt können andere Personen die unverschlossenen Räume uneingeschränkt nutzen. Eine Person kann einen Raum nutzen, oder zwei Personen können einen Raum nutzen. Es gibt keine Einschränkungen. Aber wenn jemand einen verschlossenen Raum betreten will, muss er zur Tür laufen und nachsehen. Wenn Sie den Schlüssel haben, können Sie ihn natürlich nehmen und gehen. Wenn Sie den Schlüssel nicht haben, können Sie nur warten.
Wenn viele Leute auf den Schlüssel warten, wer bekommt ihn dann zuerst, wenn der Schlüssel zurückgegeben wird? Nicht garantiert. Wie der Typ im vorherigen Beispiel, der zwei verschlossene Räume hintereinander nutzen möchte: Wenn andere Personen auf den Schlüssel warten, wenn er ihn zurückgibt, gibt es keine Garantie dafür, dass dieser Typ ihn erneut erhalten kann. (In der JAVA-Spezifikation heißt es an vielen Stellen eindeutig, dass es keine Garantien gibt, z. B. wie lange es dauert, bis Thread.sleep() nach einer Pause wieder ausgeführt wird, welcher Thread mit derselben Priorität zuerst ausgeführt wird und wann Wird die Sperre für den Zugriff auf das Objekt aufgehoben, werden mehrere Threads im Wartepool ausgewählt. Welcher Thread Priorität erhält usw. Ich denke, die endgültige Entscheidung liegt bei der JVM. Der Grund, warum es keine Garantie gibt, liegt darin, dass die JVM die oben genannte Entscheidung trifft. Es wird nicht einfach auf der Grundlage einer Bedingung beurteilt, sondern wenn es zu viele Beurteilungsbedingungen gibt, kann dies auf den Schutz des geistigen Eigentums zurückzuführen sein Diese sind nicht unvernünftig, nicht völlig unsicher, denn der Computer selbst läuft nach Anweisungen. Auch wenn es scheinbar zufällig ist, gibt es tatsächlich Regeln, die man finden kann Zahlen werden von Menschen mit einer bestimmten Methode geschrieben und scheinen zufällig zu sein. Darüber hinaus ist die Bestimmung möglicherweise zu mühsam und bedeutungslos. Wenn Sie sich also nicht sicher sind, sind Sie nicht sicher .)
Schauen wir uns noch einmal die synchronisierten Codeblöcke an. Es unterscheidet sich geringfügig von der Synchronisationsmethode.
1. In Bezug auf die Größe sind synchronisierte Codeblöcke kleiner als synchronisierte Methoden. Sie können sich einen synchronisierten Codeblock als einen Raum in einem unverschlossenen Raum vorstellen, der durch einen gesperrten Bildschirm getrennt ist.
2. Der Synchronisationscodeblock kann den Schlüssel eines anderen Objekts auch manuell angeben. Es ist so, als würde man angeben, mit welchem Schlüssel das Schloss dieses Hauses geöffnet werden kann. Sie können auch den Schlüssel eines anderen Hauses verwenden, um es zu öffnen Um das Schloss zu öffnen, holen Sie sich diesen Schlüssel und öffnen Sie mit diesem Hausschlüssel den gesperrten Bildschirm dieses Hauses.
Denken Sie daran, dass der Schlüssel zu einem anderen Haus, den Sie erhalten haben, andere nicht daran hindert, die unverschlossenen Räume dieses Hauses zu betreten.
Warum synchronisierte Codeblöcke verwenden? Ich denke, es sollte so sein: Zunächst wirkt sich der Synchronisierungsteil des Programms auf die Betriebseffizienz aus, und eine Methode erstellt normalerweise zuerst einige lokale Variablen und führt dann einige Operationen an diesen Variablen aus, z. B. Berechnungen, Anzeigen usw. ; und Synchronisierungsabdeckungen Je mehr Code vorhanden ist, desto gravierender sind die Auswirkungen auf die Effizienz. Daher versuchen wir in der Regel, den Umfang der Auswirkungen so gering wie möglich zu halten. Wie geht das? Synchronisierte Codeblöcke. Wir synchronisieren nur die Teile einer Methode, die synchronisiert werden sollen, beispielsweise Operationen.
Darüber hinaus kann der Synchronisationscodeblock den Schlüssel angeben. Diese Funktion hat den zusätzlichen Vorteil, dass der Schlüssel eines Objekts innerhalb eines bestimmten Zeitraums belegt wird. Denken Sie daran, was ich zuvor über die Prinzipien der Verwendung von Schlüsseln unter normalen Umständen gesagt habe. Dies sind keine gewöhnlichen Umstände. Der von Ihnen erhaltene Schlüssel wird nicht für immer zurückgegeben, sondern nur, wenn Sie den synchronisierten Codeblock verlassen.
Nehmen wir die Analogie des Mannes vorhin, der zwei verschlossene Räume hintereinander nutzen wollte. Wie kann ich nach der Nutzung eines Raumes weiterhin einen anderen Raum nutzen? Verwenden Sie synchronisierte Codeblöcke. Erstellen Sie zunächst einen weiteren Thread, erstellen Sie einen Synchronisierungscodeblock und richten Sie das Schloss dieses Codeblocks auf den Hausschlüssel. Dann starte diesen Thread. Solange Sie beim Betreten des Codeblocks den Hausschlüssel greifen können, können Sie ihn behalten, bis Sie den Codeblock verlassen. Mit anderen Worten, Sie können sogar alle verschlossenen Räume in diesem Raum durchqueren und sogar schlafen (10 * 60 * 1000), aber an der Tür warten immer noch 1000 Threads auf den Schlüssel. Es macht ziemlich viel Spaß.
Lassen Sie uns über die Korrelation zwischen der Methode „sleep()“ und dem Schlüssel sprechen. Wenn ein Thread nach Erhalt des Schlüssels zum Sleep() gezwungen wird und den Synchronisierungsinhalt noch nicht abgeschlossen hat, ist der Schlüssel immer noch vorhanden. Der Schlüssel wird erst zurückgegeben, wenn er erneut ausgeführt wird und der gesamte Synchronisierungsinhalt abgeschlossen ist. Denken Sie daran, der Typ war einfach müde von der Arbeit und ging, um sich auszuruhen. Er hat das, was er tun wollte, nicht zu Ende gebracht. Um zu verhindern, dass andere den Raum betreten und darin Chaos anrichten, musste er den einzigen Schlüssel auch im Schlaf am Körper tragen.
Schließlich fragt sich vielleicht jemand: Warum brauchen wir einen Schlüssel zum Öffnen jeder Tür und nicht einen Schlüssel für jede Tür? Ich denke, das ist eine reine Frage der Komplexität. Ein Schlüssel für eine Tür ist sicherlich sicherer, bringt aber viele Probleme mit sich. Die Erstellung, Aufbewahrung, Beschaffung, Rückgabe von Schlüsseln etc. Seine Komplexität kann geometrisch zunehmen, wenn die Anzahl der Synchronisationsmethoden zunimmt, was die Effizienz erheblich beeinträchtigt. Dies kann als eine Frage des Kompromisses betrachtet werden. Wie unerwünscht ist es, die Effizienz stark zu reduzieren, um die Sicherheit ein wenig zu erhöhen.