Heim  >  Artikel  >  Java  >  Beispielanalyse des Sichtbarkeitsproblems von Java-Variablen

Beispielanalyse des Sichtbarkeitsproblems von Java-Variablen

王林
王林nach vorne
2023-05-01 22:28:091512Durchsuche

Frage: Können Synchronisierung und Schlaf auch den Zweck der Sichtbarkeit flüchtiger Threads erreichen? Die allgemeine Problembeschreibung lautet wie folgt:

Paket com.test;

importiere java.util.concurrent.TimeUnit;

öffentlicher Klassentest1 {

privater statischer boolescher Wert ist = true;

public static void main(String[] args) {

neuer Thread(new Runnable() {

@Override

public void run() {

int i = 0;

while(test1.is){

i++;

1 //synchronized (this) { } aktualisiert den Variablenwert des Hauptspeichers zwangsweise im Thread-Stapel?

2 //System.out.println("1"); println ist synchronisiert und erzwingt die Aktualisierung des Variablenwerts des Hauptspeichers im Thread-Stack?

3 //sleep lädt den Wert des Hauptspeichers neu?

// versuche es mit {

// TimeUnit.MICROSECONDS.sleep(1);

// }catch (InterruptedException e) {

// e.printStackTrace();

// }

}

}

}).start();

versuche es mit {

TimeUnit.SECONDS.sleep(1);

} Catch (InterruptedException e) {

e.printStackTrace();

}

neuer Thread(new Runnable() {

@Override

public void run() {

is = false; //Setze ist auf false, damit der obige Thread die while-Schleife beendet

}

}).start();

}

}

F: Warum wird nicht das gesamte Programm beendet? Warum wird das Programm beendet, wenn Sie einen der Codeblöcke (1, 2, 3) auskommentieren? Wird die Synchronisierung die Speichervariablenwerte zwangsweise im Thread-Stapel aktualisieren?

Beinhaltet Wissenserklärung

volatile: Dieses Schlüsselwort stellt die Sichtbarkeit von Variablen in Threads sicher, die vor dem Betrieb auf Variablen zugreifen, die durch volatile geändert wurden, und unmittelbar nach der Änderung des Arbeitsspeichers in den Hauptspeicher zurückschreiben, um sicherzustellen, dass andere Threads sichtbar sind Schlüsselwort mit derselben Wirkung ist endgültig.

synchronisiert: Alle Synchronisierungsvorgänge müssen 1. Atomizität und 2. Sichtbarkeit gewährleisten, sodass Änderungen, die im synchronisierten Block auftreten, sofort in den Hauptspeicher zurückgeschrieben werden

Schlaf: Diese Methode gibt nur CPU-Ausführungszeit auf und hebt die Sperre nicht auf.

Problemanalyse

F1: Warum wird das Programm nach dem Kommentieren des Codes nicht beendet?

A1: Da der Variablenwert „boolean is=true“ vom vorherigen Thread (als Thread A bezeichnet) in seinen eigenen Arbeitsspeicher geladen wird, ist dies möglicherweise nicht der Fall, nachdem der nachfolgende Thread (als Thread B bezeichnet) den booleschen Wert „is=false“ geändert hat sofort in den Hauptspeicher geschrieben werden (aber in dieser Frage sollte es sofort in den Hauptspeicher geschrieben werden, da der Thread nach der Ausführung von is=false beendet wird. Auch wenn er sofort in den Hauptspeicher geschrieben wird, kann es sein, dass Thread A dies nicht tut). sofort in den Arbeitsspeicher geladen werden, damit das Programm weiterläuft. Wird es nicht beendet? Daran denken die meisten von uns, aber tatsächlich wurde die JVM weitgehend für die aktuelle Hardwareebene optimiert und stellt im Wesentlichen die rechtzeitige Synchronisierung von Arbeitsspeicher und Hauptspeicher weitgehend sicher, was der Verwendung von Volatile entspricht standardmäßig. Aber nur im maximalen Umfang! Wenn die CPU-Ressourcen immer belegt sind, ist die Synchronisierung zwischen Arbeitsspeicher und Hauptspeicher, dh die Sichtbarkeit von Variablen, nicht so zeitnah! Die Schlussfolgerung wird später überprüft.

F2: Warum wird das Programm nur beendet, wenn ein Codeblock (1, 2, 3) unkommentiert ist?

A2: Die Codes mit den Zeilennummern 1 und 2 haben ein gemeinsames Merkmal, das heißt, sie beinhalten alle synchronisierte Synchronisationssperren. Daher werden, wie der Autor der Frage vermutet hat, die Variablenwerte im Hauptspeicher zwangsweise aktualisiert Thread-Stapel? Und die Schlafmethode aktualisiert auch die Variablenwerte im Hauptspeicher im Thread-Stapel? Tatsächlich haben wir zuvor gesagt, dass die Synchronisierung nur die Sichtbarkeit der Variablen im synchronisierten Block gewährleistet und sich die Variable is nicht im synchronisierten Block befindet, sodass dies offensichtlich nicht der Fall ist. Als nächstes fügen wir nach dem Code i++; den folgenden Code hinzu:

for(int k=0;k<100000;k++){

neues Objekt();

}

Führen Sie es erneut aus und das Programm wird sofort beendet! Warum? In A1 oben haben wir gesagt, dass selbst bei JVM-Optimierung die Sichtbarkeit der Daten nicht garantiert werden kann, genau wie das obige Programm ständig Schleifen ausführt, um i++-Operationen auszuführen. Und warum belegt das Programm die CPU? nach dem Hinzufügen des obigen Codes aufhören? Denn für eine große Anzahl neuer Object()-Operationen ist die CPU nicht mehr der zeitaufwändigste Vorgang. Der eigentliche Zeitaufwand sollte in der Speicherzuweisung liegen (da die Verarbeitungsgeschwindigkeit der CPU offensichtlich schneller ist als die des Speichers). , andernfalls gäbe es keine CPU-Register), sodass die CPU nach dem Leerlauf dem JVM-Optimierungsbenchmark folgt, um die Sichtbarkeit der Daten so schnell wie möglich sicherzustellen und dadurch die Variable is vom Hauptspeicher mit dem Arbeitsspeicher zu synchronisieren. Dies führt schließlich zum Ende des Programms. Aus diesem Grund beinhaltet die Methode „sleep()“ keine Synchronisierungsvorgänge, das Programm kann jedoch trotzdem beendet werden, da die Methode „sleep()“ die CPU freigibt, nicht jedoch die Sperre.

Das obige ist der detaillierte Inhalt vonBeispielanalyse des Sichtbarkeitsproblems von Java-Variablen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen