Inhaltsverzeichnis
1. Volatile-Funktion
1.1 Speichersichtbarkeitsproblem
1.2 Neuordnung von Anweisungen verhindern
2. Warum flüchtig verwenden?
Heim Java javaLernprogramm Warum muss das Schlüsselwort volatile zum Java-Singleton-Modus hinzugefügt werden?

Warum muss das Schlüsselwort volatile zum Java-Singleton-Modus hinzugefügt werden?

Apr 19, 2023 pm 02:40 PM
java volatile

    Vorwort:

    Es gibt viele Möglichkeiten, den Singleton-Modus zu implementieren, z. B. den Hungrigen Modus, den Lazy-Modus, statische innere Klassen und Aufzählungen usw. Als der Interviewer fragte: „Warum muss der Singleton-Modus hinzugefügt werden?“ „flüchtig?“, dann bezieht er sich darauf, warum private Variablen im Lazy-Modus flüchtig sein müssen?

    Der Lazy-Modus bezieht sich auf die Lazy-Loading-Methode der Objekterstellung. Das Objekt wird nicht beim Start des Programms erstellt, sondern nur, wenn es tatsächlich zum ersten Mal verwendet wird.

    Müssen Sie erklären, warum flüchtige Stoffe hinzugefügt werden? Schauen wir uns zunächst den spezifischen Implementierungscode des Lazy-Modus an:

    public class Singleton {
        // 1.防止外部直接 new 对象破坏单例模式
        private Singleton() {}
        // 2.通过私有变量保存单例对象【添加了 volatile 修饰】
        private static volatile Singleton instance = null;
        // 3.提供公共获取单例对象的方法
        public static Singleton getInstance() {
            if (instance == null) { // 第 1 次效验
                synchronized (Singleton.class) {
                    if (instance == null) { // 第 2 次效验
                        instance = new Singleton(); 
                    }
                }
            }
            return instance;
        }
    }
    Nach dem Login kopieren

    Wie aus dem obigen Code ersichtlich ist, werden if und synchronisiert im Code zweimal verwendet, um die Thread-Sicherheit und hohe Leistung sicherzustellen, um die Ausführung sicherzustellen Programm. Da es also bereits eine Synchronisierung gibt, um die Thread-Sicherheit zu gewährleisten, warum müssen wir der Variablen volatile hinzufügen? Bevor wir dieses Problem erklären, müssen wir zunächst ein erforderliches Wissen verstehen: Wozu dient flüchtig?

    1. Volatile-Funktion

    volatile hat zwei Hauptfunktionen: Erstens löst es das Problem der Speichersichtbarkeit und zweitens verhindert es die Neuordnung von Anweisungen.

    1.1 Speichersichtbarkeitsproblem

    Das sogenannte Speichersichtbarkeitsproblem bezieht sich darauf, dass mehrere Threads eine Variable gleichzeitig bearbeiten. Nachdem ein Thread den Wert der Variablen geändert hat, können andere Threads die Änderung der Variablen nicht erkennen Es handelt sich um Probleme mit der Sichtbarkeit des Speichers. Die Verwendung von Volatilität kann das Problem der Speichersichtbarkeit lösen Wenn beispielsweise Volatilität nicht hinzugefügt wird, lautet seine Implementierung wie folgt:

    private static boolean flag = false;
    public static void main(String[] args) {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                // 如果 flag 变量为 true 就终止执行
                while (!flag) {
    
                }
                System.out.println("终止执行");
            }
        });
        t1.start();
        // 1s 之后将 flag 变量的值修改为 true
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("设置 flag 变量的值为 true!");
                flag = true;
            }
        });
        t2.start();
    }
    Nach dem Login kopieren

    Die Ausführungsergebnisse des obigen Programms lauten wie folgt:

    Warum muss das Schlüsselwort volatile zum Java-Singleton-Modus hinzugefügt werden?

    Das obige Programm wurde jedoch nach N langer Ausführung immer noch nicht beendet, was bedeutet, dass Thread 1 die Änderung der Variablen überhaupt nicht wahrnahm, nachdem Thread 2 die Flag-Variable geändert hatte.

    Dann versuchen wir, dem Flag volatile hinzuzufügen. Der Implementierungscode lautet wie folgt:

    public class volatileTest {
        private static volatile boolean flag = false;
        public static void main(String[] args) {
            Thread t1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    // 如果 flag 变量为 true 就终止执行
                    while (!flag) {
    
                    }
                    System.out.println("终止执行");
                }
            });
            t1.start();
            // 1s 之后将 flag 变量的值修改为 true
            Thread t2 = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("设置 flag 变量的值为 true!");
                    flag = true;
                }
            });
            t2.start();
        }
    }
    Nach dem Login kopieren

    Die Ausführungsergebnisse des obigen Programms lauten wie folgt:

    Warum muss das Schlüsselwort volatile zum Java-Singleton-Modus hinzugefügt werden?

    Aus den obigen Ausführungsergebnissen: Wir können das nach der Verwendung von volatile sehen Es ist möglich, das Problem der Speichersichtbarkeit im Programm zu lösen.

    1.2 Neuordnung von Anweisungen verhindern

    Neuordnung von Anweisungen bedeutet, dass der Compiler oder die JVM während der Programmausführung häufig Anweisungen neu anordnet, um die Ausführungsleistung des Programms zu verbessern. Die ursprüngliche Entwurfsabsicht der Befehlsneuordnung ist in der Tat sehr gut und kann auch in einem einzelnen Thread eine große Rolle spielen. In Multithreads kann die Verwendung der Befehlsneuordnung jedoch zu Thread-Sicherheitsproblemen führen.

    Das sogenannte Thread-Sicherheitsproblem bedeutet, dass die Ausführungsergebnisse des Programms nicht unseren Erwartungen entsprechen. Wenn beispielsweise das erwartete korrekte Ergebnis 0 ist, das Ausführungsergebnis des Programms jedoch 1 ist, handelt es sich um ein Thread-Sicherheitsproblem.

    Die Verwendung von volatile kann die Neuordnung von Anweisungen verhindern und so sicherstellen, dass das Programm korrekt ausgeführt werden kann, wenn es in mehreren Threads ausgeführt wird.

    2. Warum flüchtig verwenden?

    Zurück zum Thema: Wir verwenden flüchtig im Singleton-Modus, hauptsächlich weil flüchtig die Neuordnung von Anweisungen verhindern und so den normalen Betrieb des Programms sicherstellen kann. Einige Leser stellen hier möglicherweise Fragen: Wird die Synchronisierung nicht bereits verwendet, um die Thread-Sicherheit zu gewährleisten? Warum also Volatilität hinzufügen? Schauen Sie sich den Code unten an:

    public class Singleton {
        private Singleton() {}
        // 使用 volatile 禁止指令重排序
        private static volatile Singleton instance = null;
        public static Singleton getInstance() {
            if (instance == null) { // ①
                synchronized (Singleton.class) {
                    if (instance == null) {
                        instance = new Singleton(); // ②
                    }
                }
            }
            return instance;
        }
    }
    Nach dem Login kopieren

    Achten Sie auf den obigen Code. Ich habe die beiden Codezeilen bei ① und ② markiert. Das Hinzufügen von volatile zu privaten Variablen dient hauptsächlich dazu, die Neuordnung von Anweisungen während der Ausführung von ② zu verhindern, d. h. die Ausführung von „instance = new Singleton()“. Diese Codezeile scheint nur ein Prozess zum Erstellen eines Objekts zu sein. aber seine tatsächliche Ausführung ist in die folgenden 3 Schritte unterteilt:

    • Speicherplatz schaffen.

    • Initialisieren Sie das Objekt Singleton im Speicherbereich.

    • Weisen Sie die Speicheradresse dem Instanzobjekt zu (nach Ausführung dieses Schritts ist die Instanz nicht gleich Null).

    Stellen Sie sich vor: Wenn flüchtig nicht hinzugefügt wird, führt Thread 1 möglicherweise eine Neuordnung der Anweisungen durch, wenn er ② des obigen Codes ausführt, und ordnet die ursprüngliche Ausführungsreihenfolge von 1, 2 und 3 in 1, 3, 2 um . Wenn jedoch unter besonderen Umständen Thread 1 den ersten Schritt des obigen Codes ausführt, nachdem Thread 1 Schritt 3 ausgeführt hat, wird festgestellt, dass das Instanzobjekt nicht null ist, Thread 1 die Instanziierung des Objekts jedoch noch nicht abgeschlossen hat Thread 2 erhält ein „halbes“ Objekt, das instanziiert wird, was zu einem Fehler bei der Programmausführung führt. Aus diesem Grund wird volatile zur privaten Variablen hinzugefügt.

    Das obige ist der detaillierte Inhalt vonWarum muss das Schlüsselwort volatile zum Java-Singleton-Modus hinzugefügt werden?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

    Erklärung dieser Website
    Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

    Heiße KI -Werkzeuge

    Undresser.AI Undress

    Undresser.AI Undress

    KI-gestützte App zum Erstellen realistischer Aktfotos

    AI Clothes Remover

    AI Clothes Remover

    Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

    Undress AI Tool

    Undress AI Tool

    Ausziehbilder kostenlos

    Clothoff.io

    Clothoff.io

    KI-Kleiderentferner

    AI Hentai Generator

    AI Hentai Generator

    Erstellen Sie kostenlos Ai Hentai.

    Heißer Artikel

    R.E.P.O. Energiekristalle erklärten und was sie tun (gelber Kristall)
    1 Monate vor By 尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O. Beste grafische Einstellungen
    1 Monate vor By 尊渡假赌尊渡假赌尊渡假赌
    Will R.E.P.O. Crossplay haben?
    1 Monate vor By 尊渡假赌尊渡假赌尊渡假赌

    Heiße Werkzeuge

    Notepad++7.3.1

    Notepad++7.3.1

    Einfach zu bedienender und kostenloser Code-Editor

    SublimeText3 chinesische Version

    SublimeText3 chinesische Version

    Chinesische Version, sehr einfach zu bedienen

    Senden Sie Studio 13.0.1

    Senden Sie Studio 13.0.1

    Leistungsstarke integrierte PHP-Entwicklungsumgebung

    Dreamweaver CS6

    Dreamweaver CS6

    Visuelle Webentwicklungstools

    SublimeText3 Mac-Version

    SublimeText3 Mac-Version

    Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

    Perfekte Zahl in Java Perfekte Zahl in Java Aug 30, 2024 pm 04:28 PM

    Leitfaden zur perfekten Zahl in Java. Hier besprechen wir die Definition, Wie prüft man die perfekte Zahl in Java?, Beispiele mit Code-Implementierung.

    Weka in Java Weka in Java Aug 30, 2024 pm 04:28 PM

    Leitfaden für Weka in Java. Hier besprechen wir die Einführung, die Verwendung von Weka Java, die Art der Plattform und die Vorteile anhand von Beispielen.

    Smith-Nummer in Java Smith-Nummer in Java Aug 30, 2024 pm 04:28 PM

    Leitfaden zur Smith-Zahl in Java. Hier besprechen wir die Definition: Wie überprüft man die Smith-Nummer in Java? Beispiel mit Code-Implementierung.

    Fragen zum Java Spring-Interview Fragen zum Java Spring-Interview Aug 30, 2024 pm 04:29 PM

    In diesem Artikel haben wir die am häufigsten gestellten Fragen zu Java Spring-Interviews mit ihren detaillierten Antworten zusammengestellt. Damit Sie das Interview knacken können.

    Brechen oder aus Java 8 Stream foreach zurückkehren? Brechen oder aus Java 8 Stream foreach zurückkehren? Feb 07, 2025 pm 12:09 PM

    Java 8 führt die Stream -API ein und bietet eine leistungsstarke und ausdrucksstarke Möglichkeit, Datensammlungen zu verarbeiten. Eine häufige Frage bei der Verwendung von Stream lautet jedoch: Wie kann man von einem Foreach -Betrieb brechen oder zurückkehren? Herkömmliche Schleifen ermöglichen eine frühzeitige Unterbrechung oder Rückkehr, aber die Stream's foreach -Methode unterstützt diese Methode nicht direkt. In diesem Artikel werden die Gründe erläutert und alternative Methoden zur Implementierung vorzeitiger Beendigung in Strahlverarbeitungssystemen erforscht. Weitere Lektüre: Java Stream API -Verbesserungen Stream foreach verstehen Die Foreach -Methode ist ein Terminalbetrieb, der einen Vorgang für jedes Element im Stream ausführt. Seine Designabsicht ist

    Zeitstempel für Datum in Java Zeitstempel für Datum in Java Aug 30, 2024 pm 04:28 PM

    Anleitung zum TimeStamp to Date in Java. Hier diskutieren wir auch die Einführung und wie man Zeitstempel in Java in ein Datum konvertiert, zusammen mit Beispielen.

    Java -Programm, um das Kapselvolumen zu finden Java -Programm, um das Kapselvolumen zu finden Feb 07, 2025 am 11:37 AM

    Kapseln sind dreidimensionale geometrische Figuren, die aus einem Zylinder und einer Hemisphäre an beiden Enden bestehen. Das Volumen der Kapsel kann berechnet werden, indem das Volumen des Zylinders und das Volumen der Hemisphäre an beiden Enden hinzugefügt werden. In diesem Tutorial wird erörtert, wie das Volumen einer bestimmten Kapsel in Java mit verschiedenen Methoden berechnet wird. Kapselvolumenformel Die Formel für das Kapselvolumen lautet wie folgt: Kapselvolumen = zylindrisches Volumenvolumen Zwei Hemisphäre Volumen In, R: Der Radius der Hemisphäre. H: Die Höhe des Zylinders (ohne die Hemisphäre). Beispiel 1 eingeben Radius = 5 Einheiten Höhe = 10 Einheiten Ausgabe Volumen = 1570,8 Kubikeinheiten erklären Berechnen Sie das Volumen mithilfe der Formel: Volumen = π × R2 × H (4

    Wie führe ich Ihre erste Spring -Boot -Anwendung in der Spring Tool Suite aus? Wie führe ich Ihre erste Spring -Boot -Anwendung in der Spring Tool Suite aus? Feb 07, 2025 pm 12:11 PM

    Spring Boot vereinfacht die Schaffung robuster, skalierbarer und produktionsbereiteter Java-Anwendungen, wodurch die Java-Entwicklung revolutioniert wird. Der Ansatz "Übereinkommen über Konfiguration", der dem Feder -Ökosystem inhärent ist, minimiert das manuelle Setup, Allo

    See all articles