Bei unserer täglichen Entwicklungsarbeit sind wir mehr oder weniger Multithread-Programmierung oder einigen Parallelitätsproblemen ausgesetzt. Mit der Aktualisierung von Betriebssystemen und Systemhardware wird in unserer Entwicklung zunehmend gleichzeitige Programmierung verwendet Die Verwendung von Multithreading dient dazu, die Systemressourcen besser zu nutzen. Wenn wir jedoch Multithreading verwenden, treten zunächst einige Probleme auf.
private static int i = 0; private static void increse(){ i++; } public static void main(String[] args) { Thread[] threads = new Thread[20]; for (int i = 0; i < threads.length; i++){ threads[i] = new Thread(new Runnable() { @Override public void run() { for (int j = 0; j < 10000; j++){ increse(); } } }); threads[i].start(); } while (Thread.activeCount() > 1){ Thread.yield(); } System.out.println(i); }
Zuallererst gibt es kein Problem, wenn Sie sich diesen Code ansehen, aber wenn er sich in einer Multithread-Umgebung befindet, sind die Ergebnisse der Ausführung dieses Codes grundsätzlich unterschiedlich. Hier werden 20 Threads gestartet. und dann ruft jeder Thread die Methode increse()
auf, um eine Zuweisungsoperation für die Variable i
durchzuführen. Die erwartete Ausgabe sollte 200000
sein, aber warum ist die Ausgabe jedes Mal anders? Der Grund liegt in diesem Ort i++
Dies ist die Hauptursache für Parallelitätsprobleme. Warum gibt es bei diesem scheinbar einfachen i++
ein solches Problem? Lassen Sie es uns einfach anhand von java内存模型
(JMM) verstehen. Erstens legt JMM
fest, dass jeder Thread beim Ausführen einen Arbeitsspeicher hat, und dann wird die Variable i
jedes Mal im Hauptspeicher gespeichert Um es einfach auszudrücken: Nachdem ein Thread die Variable i
berechnet und das Ergebnis erhalten hat, wurden die Daten nicht im Hauptspeicher aktualisiert Diesmal wurde der ursprüngliche Wert von anderen Threads abgerufen. Mit anderen Worten, es ist nicht bekannt, ob die in diesem Thread erhaltenen Daten die neuesten sind. Dies ist jedoch nur eine kurze Erklärung aus der Perspektive von JMM
. Diese scheinbar einfache Operation von i++
enthält tatsächlich drei Operationen: Ermitteln des Werts von i
, Erhöhen von i
und Erhöhen von i
. Während dieser Vorgänge haben andere Threads viel Zeit, um viele Dinge zu erledigen. Dann fragen sich einige Leute vielleicht, ob es ausreicht, diesen i++
-Vorgang zu synchronisieren. Ja, wie synchronisiert man es?
Einige Leute sagen, dass es ausreicht, volatile
zum Ändern der Variablen i
zu verwenden? Ja, das Schlüsselwort java
in volatile
bietet zwar eine Synchronisierungsfunktion, aber warum hat eine Änderung hier immer noch keine Auswirkung? Der Grund dafür ist, dass, wenn eine Variable mit volatile geändert wird, es anderen Threads nur ermöglicht, den Wert der aktuellen Variablen sofort zu kennen. Dies wird als 可见性
bezeichnet, aber es kann die Probleme der i++
-Operationen immer noch nicht lösen Was? Um damit umzugehen, hat jemand anderes vorgeschlagen, das Schlüsselwort synchronized
zu verwenden. Ich muss zugeben, dass dieses Schlüsselwort tatsächlich sehr mächtig ist und dieses Problem lösen kann ? Das heißt, um es einfach auszudrücken: synchronized
gehört zur JVM-Ebene. Methoden oder Codeblöcke mit diesem Schlüsselwort werden letztendlich als monitorenter
und monitorexit
interpretiert 🎜> Geben Sie Parameter ein, um das Objekt anzugeben, das gesperrt oder entsperrt werden soll, etwa so: reference
public synchronized String f(){ //code } synchronized(object){ //code }Wenn wir das sehen, sollten wir verstehen, warum
das Problem des oben genannten Programms lösen kann, aber wir sollten es auch tun Eines klarstellen Das Konzept ist synchronized
Mit anderen Worten: Wenn wir uns mit einigen Multithread-Problemen befassen, sollten wir sicherstellen, dass einige Operationen an gemeinsam genutzten Daten atomar sind, um die Korrektheit sicherzustellen Wenn Sie eine Idee haben, fassen wir zusammen, welche Punkte beim Umgang mit Multithreading-Problemen zu beachten sind. 原子性
, 可见性
, 原子性
Diese Punkte sind eine Voraussetzung, um sicherzustellen, dass Multithreading korrekt sein kann. Was Ordnung betrifft, geht es um die Neuordnung von Speicheranweisungen, die nicht Gegenstand der Diskussion ist. Wir werden später darauf eingehen. 有序性
public String f(String s1, String s2, String s3){ return s1 + s2 +s3; }Dies ist eine Methode zum Spleißen von Zeichenfolgen. Schauen wir uns an, wie die JVM das hier macht. Verwandte Empfehlungen:
Detaillierte Erläuterung der Java-Thread-Synchronisation und Synchronisationsmethoden
Detaillierte Einführung in den synchronisierten Block des Java-Synchronisationsblocks Verwenden Sie
Das obige ist der detaillierte Inhalt vonLernartikel: Informationen zur Synchronisierung in Java. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!