Heim  >  Artikel  >  Java  >  Ich habe gehört, dass dies eine schwierige Java-Interviewfrage ist?

Ich habe gehört, dass dies eine schwierige Java-Interviewfrage ist?

王林
王林nach vorne
2021-01-11 09:54:052457Durchsuche

Ich habe gehört, dass dies eine schwierige Java-Interviewfrage ist?

Werfen wir zunächst einen Blick auf den Inhalt der Frage:

(Teilen von Lernvideos: Java-Video-Tutorial)

public class TestSync2 implements Runnable {
    int b = 100;          

    synchronized void m1() throws InterruptedException {
        b = 1000;
        Thread.sleep(500); //6
        System.out.println("b=" + b);
    }

    synchronized void m2() throws InterruptedException {
        Thread.sleep(250); //5
        b = 2000;
    }

    public static void main(String[] args) throws InterruptedException {
        TestSync2 tt = new TestSync2();
        Thread t = new Thread(tt);  //1
        t.start(); //2

        tt.m2(); //3
        System.out.println("main thread b=" + tt.b); //4
    }

    @Override
    public void run() {
        try {
            m1();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

Das Ausgabeergebnis dieses Programms?

Ergebnisse der Programmausgabe

main thread b=2000
b=1000
或
main thread b=1000
b=1000

Wissenspunkte prüfen

Instanzsperre synchronisieren.

Speichersichtbarkeit bei Parallelität.

(Empfehlungen für weitere verwandte Interviewfragen: Java-Interviewfragen und -antworten)

In Java sind Multithread-Programme am schwierigsten zu verstehen und zu debuggen, und oft werden die Ausführungsergebnisse nicht so ausgeführt, wie wir es uns vorgestellt haben. Daher ist Multithreading in Java besonders schwierig. Als ich an der Uni den C-Sprachtest der Stufe 2 absolvierte, waren die Fragen darin ++ und viele andere vorrangige Fragen, die sich mit dem gewünschten Endergebnis befassten um einige dieser Fragen zu beantworten. Merken Sie es sich einfach, aber Java-Multithreading muss noch gut verstanden werden, und das Auswendiglernen wird nicht funktionieren.

Das Folgende beginnt mit einer einfachen Analyse:

Diese Frage betrifft 2 Threads (Hauptthread, Unterthread), und die Schlüsselwörter umfassen synchronisiert und Thread.sleep.
Das synchronisierte Schlüsselwort ist immer noch ziemlich kompliziert (vielleicht wird es manchmal nicht richtig verstanden, sodass die obige Frage etwas missverstanden wird). Seine Funktion besteht darin, eine Thread-Synchronisation zu erreichen (es gibt viele Möglichkeiten, eine Thread-Synchronisation zu erreichen, es ist nur eine Methode Das wird in den folgenden Artikeln besprochen. Sie müssen einige Implementierungen des Meisters Doug Lea studieren. Seine Aufgabe besteht darin, den Code zu sperren, der synchronisiert werden muss, sodass jeweils nur ein Thread in den Synchronisierungsblock eintreten kann (eigentlich ein Pessimist). Strategie), um sicherzustellen, dass sich der Thread nur an die Sicherheit erinnert.

Verwendung des allgemeinen Schlüsselworts synchronisiert

Geben Sie das Sperrobjekt an: Sperren Sie das angegebene Objekt. Die Sperre des angegebenen Objekts muss aktiviert werden, bevor Sie den Synchronisierungscode eingeben. Direkte Einwirkung auf die Instanzmethode: entspricht dem Sperren der aktuellen Instanz. Bevor Sie den Synchronisierungscode eingeben, müssen Sie die Sperre der aktuellen Instanz erhalten. Direktes Einwirken auf statische Methoden: Entspricht dem Sperren der aktuellen Klasse. Vor der Eingabe des Synchronisationscodes muss die Sperre der aktuellen Klasse erhalten werden.

Im obigen Code gehört die synchronisierte Nutzung tatsächlich zur zweiten Situation. Direkte Einwirkung auf die Instanzmethode: entspricht dem Sperren der aktuellen Instanz. Bevor Sie den Synchronisierungscode eingeben, müssen Sie die Sperre der aktuellen Instanz erhalten.

Mögliche Missverständnisse

Aufgrund des unzureichenden Verständnisses von synchronisierten Methoden betreiben unsere Multithreads oft eine synchronisierte Methode. Wenn zwei Threads zwei verschiedene synchronisierte Methoden aufrufen, denken sie, dass es in dieser Idee ein Missverständnis gibt . Direkte Einwirkung auf die Instanzmethode: entspricht dem Sperren der aktuellen Instanz. Bevor Sie den Synchronisierungscode eingeben, müssen Sie die Sperre der aktuellen Instanz erhalten. Wenn man die synchronisierte Methode aufruft. Es spielt keine Rolle, ob der andere eine normale Methode aufruft und es keine Wartebeziehung zwischen den beiden gibt.

Diese sind für die spätere Analyse sehr nützlich.

Thread.sleep

bewirkt, dass der aktuelle Thread (d. h. der Thread, der diese Methode aufruft) die Ausführung für einen bestimmten Zeitraum anhält, um anderen Threads die Möglichkeit zu geben, die Ausführung fortzusetzen, die Objektsperre wird jedoch nicht aufgehoben. Das heißt, wenn ein synchronisierter Synchronisationsblock vorhanden ist, können andere Threads immer noch nicht auf die gemeinsam genutzten Daten zugreifen. Beachten Sie, dass diese Methode Ausnahmen abfangen sollte, was für die nachfolgende Analyse sehr nützlich ist. Weitere Informationen finden Sie in meiner System Learning Java High Concurrency Series 2.

Analyseprozess:

Java wird von der Hauptmethode ausgeführt. Es wurde oben erwähnt, dass es sinnlos ist, die Thread-Priorität zu ändern, wenn die beiden Programme nicht nacheinander ausgeführt wurden Sobald dieser Code ausgeführt wird, wurde der Hauptthread main ausgeführt. Für die Attributvariable int b = 100 tritt bei der Ausführung von Schritt 1 (Thread t = new Thread(tt); //1) aufgrund der Verwendung von synchronisiert kein Sichtbarkeitsproblem auf (es ist keine flüchtige Deklaration erforderlich). Thread Es befindet sich im neuen Zustand und hat noch nicht begonnen zu arbeiten.

Beim Ausführen der beiden Schritte (t.start(); //2) wird der Thread tatsächlich gestartet und wechselt in den ausführbaren Zustand. Der ausführbare Zustand zeigt an, dass er ausgeführt werden kann und alles bereit ist. Dies ist jedoch nicht der Fall. Dies bedeutet, dass es auf der CPU ausgeführt werden muss. Ob es tatsächlich ausgeführt wird, hängt von der Planung der Dienst-CPU ab. Wenn Sie Schritt 3 hier ausführen, müssen Sie zuerst die Sperre erhalten (da Start die native Methode aufrufen muss und nach Abschluss der Verwendung alles bereit ist. Dies bedeutet jedoch nicht, dass es auf der CPU ausgeführt werden muss. Ob dies tatsächlich der Fall ist Die Ausführung hängt von der Planung der Dienst-CPU ab. Die Ausführungsmethode wird später aufgerufen und die m1-Methode ausgeführt.

Tatsächlich spielt es keine Rolle, ob Thread.sheep in den beiden synchronisierten Methoden verwendet wird oder nicht. Dies dient wahrscheinlich nur dazu, die Schwierigkeit der Verwirrung zu erhöhen. Wenn Schritt 3 ausgeführt wird, ist der untergeordnete Thread tatsächlich bald bereit, aber aufgrund der Existenz von synchronisiert und der Tatsache, dass er auf demselben Objekt arbeitet, muss der untergeordnete Thread warten. Da die Ausführungsreihenfolge in der Hauptmethode sequentiell ist, muss Schritt 4 nach Abschluss von Schritt 3 abgeschlossen werden. Da Schritt 3 abgeschlossen ist, kann der Unterthread m1 ausführen.

Hier gibt es ein Problem bei Multithreads, die es zuerst in Schritt 4 erhalten, dann ist der Hauptthread b=2000, wenn b möglicherweise 1000 oder das mögliche Ergebnis zugewiesen wurde wird in Schritt 4 ausgegeben, bevor es Zeit hat, es zuzuweisen. Es ist der Hauptthread b=1000 oder der Hauptthread b=2000. Wenn Schritt 6 entfernt wird, wird b= zuerst ausgeführt und der Hauptthread b= wird zuerst ausgeführt. Aber da es 6 Schritte gibt, steht der Hauptthread b= auf jeden Fall vorne, sodass es von der Situation abhängt, ob er 1000 oder 2000 ist. Danach ist b=1000 definitiv festgelegt.

Einige Vorschläge für Multithreading

Threads sind ebenfalls sehr wertvoll, daher wird empfohlen, häufig Thread-Pools zu verwenden. Dies ist besonders wichtig und Sie müssen sich dessen bewusst sein . Geben Sie dem Thread einen Namen. Wenn die Online-CPU hoch ist, müssen Sie den erweiterten JStack verwenden. Es ist viel praktischer, wenn es einen Namen gibt. Multithreading erfordert besondere Aufmerksamkeit für Thread-Sicherheitsprobleme. Außerdem müssen Sie verstehen, ob JDK Thread-sicher oder unsicher ist, damit bei der Verwendung keine unerklärlichen Probleme auftreten.

Es gibt auch einige Fähigkeiten, die ich in den folgenden Artikeln teilen werde. Ich hoffe, dass jeder mehr Zeit damit verbringen wird.

Einige Debugging-Fähigkeiten für Multithreading

Aufgrund von Haltepunkten müssen alle Threads angehalten werden, wenn sie den Haltepunkt passieren, was dazu führt, dass dieser Punkt ständig unterbrochen wird. Es gibt bedingte Haltepunkte in Eclipse, wenn die Bedingungen erfüllt sind kann zu gegebener Zeit aufhören, das ist also praktisch.

Verwandte Empfehlungen: Java-Einführungs-Tutorial

Das obige ist der detaillierte Inhalt vonIch habe gehört, dass dies eine schwierige Java-Interviewfrage ist?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

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