Heim  >  Artikel  >  Java  >  Ein Beispiel, um zu verstehen, wie das synchronisierte Schlüsselwort in Java verwendet wird

Ein Beispiel, um zu verstehen, wie das synchronisierte Schlüsselwort in Java verwendet wird

WBOY
WBOYnach vorne
2022-10-08 16:02:541701Durchsuche

Dieser Artikel vermittelt Ihnen relevantes Wissen über Java und stellt hauptsächlich verwandte Themen zum synchronisierten Schlüsselwort vor, einschließlich der Verwendung von Synchronisationsmethoden, der Verwendung von Synchronisationsanweisungen oder -blöcken, was Synchronisation ist und warum Synchronisation erforderlich ist Schauen Sie sich den Inhalt unten an. Ich hoffe, er wird für alle hilfreich sein.

Empfohlene Studie: „Java-Video-Tutorial

In der täglichen Entwicklung stößt man häufig auf das synchronisierte Schlüsselwort. Wissen Sie, wie man synchronisiert verwendet? Dieser Artikel wird es Ihnen vorstellen.

Wir haben zwei Möglichkeiten, die Synchronisierung zu verwenden:

  • Synchronisierte Methoden verwenden
  • Synchronisierte Anweisungen oder Blöcke verwenden

Synchronisierte Methoden verwenden

Um eine Methode zu synchronisieren, fügen Sie einfach das synchronisierte Schlüsselwort zu ihrer Deklaration hinzu:

public class SynchronizedDemo {

    private int i = 0;

    public synchronized void add() {
        i++;
    }

    public synchronized void del() {
        i--;
    }

    public synchronized int getValue() {
        return i;
    }
}

Wie im obigen Code gezeigt, gibt es drei Synchronisationsmethoden:

  • add()
  • del()
  • getValue()

Jede Methode wird nur einmal gleichzeitig für dasselbe Objekt aufgerufen. Wenn beispielsweise ein Thread add () aufruft, werden andere Threads blockiert, bis der erste Thread die Verarbeitung der Methode add () abgeschlossen hat.

Verwenden Sie synchronisierte Anweisungen oder Blöcke

    public void del(int value){

        synchronized(this){
            this.i -= value;
        }
    }

Im obigen Code wird synchronisiert vor einem {}-Code hinzugefügt, der einen synchronisierten Codeblock darstellt.

Die oben genannten zwei Möglichkeiten, das synchronisierte Schlüsselwort zu verwenden, stellen wir kurz die Konzepte im Zusammenhang mit der Synchronisierung vor.

Was ist Synchronisation?

Synchronisierung ist ein Prozess, der den Zugriff mehrerer Threads auf eine gemeinsame Ressource steuert und so inkonsistente Ergebnisse vermeidet. Der Hauptzweck der Verwendung der Synchronisierung besteht darin, inkonsistentes Verhalten von Threads zu vermeiden und Thread-Interferenzen zu verhindern.

Sie können das synchronisierte Schlüsselwort in Java verwenden, um Synchronisierungseffekte zu erzielen, die nur auf Methoden und Blöcke angewendet werden können, nicht auf Variablen und Klassen.

Warum müssen wir synchronisieren?

Schauen wir uns zunächst einen Code an:

public class SynchronizedDemo {

    int i;

    public void increment() {
        i++;
    }

    public static void main(String[] args) {
        SynchronizedDemo synchronizedDemo = new SynchronizedDemo();
        synchronizedDemo.increment();
        System.out.println("计算值为:" + synchronizedDemo.i);
    }
}

Jedes Mal, wenn die increment()-Methode aufgerufen wird, wird der berechnete Wert um 1 erhöht:

Bei 2-maligem Aufruf werden 2 hinzugefügt, wenn sie aufgerufen wird 3 Mal werden 3 hinzugefügt, und wenn es 4 Mal aufgerufen wird, werden 3 hinzugefügt:

public class SynchronizedDemo {

    int i;

    public void increment() {
        i++;
    }

    public static void main(String[] args) {
        SynchronizedDemo synchronizedDemo = new SynchronizedDemo();
        synchronizedDemo.increment();
        synchronizedDemo.increment();
        synchronizedDemo.increment();
        synchronizedDemo.increment();
        System.out.println("计算值为:" + synchronizedDemo.i);
    }
}

Das Ergebnis der Berechnung zu diesem Zeitpunkt ist wie erwartet, das Ergebnis ist 10.

Dies ist eine Single-Threaded-Situation, alles ist so gut, aber ist das wirklich so? Wie würde es aussehen, wenn es eine Multithread-Umgebung wäre?

Lassen Sie uns unten die Multithreading-Situation demonstrieren!

public class SynchronizedDemo {

    int i;

    public void increment() {
        i++;
    }

    public static void main(String[] args) {
        SynchronizedDemo synchronizedDemo = new SynchronizedDemo();
        Thread thread = new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                synchronizedDemo.increment();
            }
        });
        thread.start();
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("计算值为:" + synchronizedDemo.i);
    }
}

Wie im obigen Code gezeigt, haben wir zwei Threads Thread1 und Thread2 erstellt und jeder Thread hat increment() 1000 Mal aufgerufen. Theoretisch sollte der endgültige gedruckte Wert

2000

sein, da sich der Wert ändert, nachdem Thread1 Inkrement aufruft () 1000 Mal wird 1000. Nachdem Thread2 1000 Mal Inkrement () aufruft, wird der Wert 2000.

Lassen Sie es uns ausführen und das Ergebnis sehen:

Das Ergebnis ist anders als wir dachten. Es ist weniger als 2000. Führen wir es noch einmal aus:

Das Ergebnis ist immer noch kleiner als 2000.

Warum ist das so?

Da Multithreading die parallele Verarbeitung unterstützt, ist es immer möglich, dass zwei Threads gleichzeitig den Wert des Zählers abrufen und daher beide den gleichen Zählerwert erhalten. In diesem Fall wird also der Wert des Zählers nicht erhöht Zähler zweimal, er erhöht ihn nur einmal.

Wie kann man diese Situation vermeiden?

Verwenden Sie das synchronisierte Schlüsselwort, um es zu lösen.

Wir müssen nur synchronisiert zur Methode increment() hinzufügen:

public class SynchronizedDemo {

    int i;

    public void increment() {
        i++;
    }

    public static void main(String[] args) {
        SynchronizedDemo synchronizedDemo = new SynchronizedDemo();

        Thread thread1 = new Thread(() -> {
            for (int i = 1; i <= 1000; i++) {
                synchronizedDemo.increment();
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 1; i <= 1000; i++) {
                synchronizedDemo.increment();
            }
        });

        thread1.start();
        thread2.start();
        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("计算值为:" + synchronizedDemo.i);
    }
}

Lass es uns zu diesem Zeitpunkt noch einmal ausführen:

Sie können sehen, dass der Wert 2000 ist.

Wir erhöhen die Anzahl der Berechnungen auf 10.000 mal:

public class SynchronizedDemo {

    int i;

    public synchronized void increment() {
        i++;
    }

    public static void main(String[] args) {
        SynchronizedDemo synchronizedDemo = new SynchronizedDemo();

        Thread thread1 = new Thread(() -> {
            for (int i = 1; i <= 1000; i++) {
                synchronizedDemo.increment();
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 1; i <= 1000; i++) {
                synchronizedDemo.increment();
            }
        });

        thread1.start();
        thread2.start();
        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("计算值为:" + synchronizedDemo.i);
    }
}

Das Ausführungsergebnis ist:

Es ist ersichtlich, dass ein wenig Synchronisierung dieses Problem so einfach löst.

Das Prinzip dahinter besteht darin, dass Thread 1 die Methode automatisch sperrt, wenn sie synchronisiert ist. Zu diesem Zeitpunkt besitzt nur Thread 1 die Sperre und andere Threads können nur warten, bis Thread 1 die Methode freigibt Erst nach dem Sperren der Sperre kann Thread 2 am Aufruf teilnehmen.

Wenn Thread 2 inkrementiert (), erhält Thread 1 die Sperre und Thread 1 wartet, bis Thread 2 die Sperre aufhebt. Auf diese Weise treten während dieses Vorgangs keine Berechnungsfehler auf.

Zusammenfassung

  • Das synchronisierte Schlüsselwort ist die einzige Möglichkeit, einen Block oder eine Methode zu synchronisieren.
  • Das synchronisierte Schlüsselwort bietet Sperrfunktionen, die sicherstellen, dass keine Race Conditions zwischen Threads auftreten. Nach dem Sperren kann der Thread nur Daten aus dem Hauptspeicher lesen. Nach dem Lesen der Daten wird der Schreibvorgang gelöscht, bevor die Sperre aufgehoben werden kann. Das Schlüsselwort
  • synchronized trägt auch dazu bei, eine Neuordnung von Programmanweisungen zu vermeiden.

Empfohlenes Lernen: „Java-Video-Tutorial

Das obige ist der detaillierte Inhalt vonEin Beispiel, um zu verstehen, wie das synchronisierte Schlüsselwort in Java verwendet wird. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

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