検索
ホームページJava&#&チュートリアルJava シングルトン モードに volatile キーワードを追加する必要があるのはなぜですか?

    前書き:

    シングルトン モードを実装するには、ハングリー モード、レイジー モード、静的内部クラス、列挙型など、インタビュアーが「なぜ volatile をシングルトン モードに追加する必要があるのですか?」と尋ねたとき、彼はなぜ Lazy モードのプライベート変数を volatile に追加する必要があるのか​​について言及しています。

    遅延モードとは、オブジェクト作成の遅延読み込み方式を指し、オブジェクトはプログラムの起動時には作成されず、実際に初めて使用されるときにのみ作成されます。

    なぜ volatile を追加する必要があるのか​​説明していただけますか?まず、遅延モードの具体的な実装コードを見てみましょう:

    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;
        }
    }

    上記のコードからわかるように、スレッドの安全性と高いパフォーマンスを確保するために、コード内で if と synchronized が 2 回使用されています。プログラムの実行を確実にするため。では、スレッドの安全性を確保するためにすでに synchronized が行われているのに、なぜ変数に volatile を追加する必要があるのでしょうか?この問題を説明する前に、まず前提条件となる知識を理解する必要があります: volatile の用途は何ですか?

    1. Volatile 関数

    volatile には 2 つの主な機能があります。1 つ目はメモリの可視性の問題を解決し、2 つ目は命令の並べ替えを防止します。

    1.1 メモリ可視性の問題

    いわゆるメモリ可視性問題とは、複数のスレッドが同時に変数を操作する場合を指します。1 つのスレッドが変数の値を変更した後、他のスレッドがスレッド 変数の変更は認識できません。これはメモリの可視性の問題です。 volatile を使用すると、メモリ可視性の問題を解決できます。 次のコードのように、volatile が追加されていない場合、その実装は次のようになります。

    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();
    }

    実行結果上記のプログラムは次のようになります:

    Java シングルトン モードに volatile キーワードを追加する必要があるのはなぜですか?

    ただし、上記のプログラムを N 回実行してもまだ終了していません。これは、スレッド 2 が変更されたことを示しています。フラグ変数、スレッド 1 は変数の変更を認識しませんでした。

    次に、フラグに volatile を追加してみます。実装コードは次のとおりです。

    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();
        }
    }

    上記プログラムの実行結果は次のようになります。

    Java シングルトン モードに volatile キーワードを追加する必要があるのはなぜですか?

    上記の実行結果から、volatile を使用するとプログラム内のメモリ可視性の問題を解決できることがわかります。

    1.2 命令の並べ替えの防止

    命令の並べ替えとは、プログラムの実行中に、コンパイラまたは JVM がプログラムの実行パフォーマンスを向上させるために命令の順序を頻繁に並べ替えることを意味します。命令の並べ替えの本来の設計意図は確かに非常に優れており、シングル スレッドでも大きな役割を果たすことができますが、マルチスレッドでは命令の並べ替えを使用するとスレッドの安全性の問題が発生する可能性があります。

    いわゆるスレッド セーフティの問題とは、プログラムの実行結果が期待と一致しないことを指します。たとえば、予期した正しい結果が 0 であるにもかかわらず、プログラムの実行結果が 1 である場合、これはスレッド セーフティの問題です。

    volatile を使用すると命令の並べ替えを禁止できるため、複数のスレッドで実行するときにプログラムを正しく実行できます。

    2. なぜ volatile を使用するのでしょうか?

    話題に戻りますが、 シングルトン モードでは volatile を使用します。主な理由は、volatile は命令の並べ替えを禁止し、それによってプログラム の通常の動作を確保できるからです。ここで読者の中には、スレッドの安全性を確保するために synchronized がすでに使用されているのではないかという疑問を持つ人もいるかもしれません。では、なぜ volatile を追加するのでしょうか?次のコードを見てください:

    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;
        }
    }

    上記のコードに注目してください。コードの 2 行の①と②にマークを付けました。プライベート変数に volatile を追加するのは、主に②の実行時、つまり「instance = new Singleton()」の実行時に命令が並べ替えられるのを防ぐためです。実際の実行は次の 3 つのステップに分かれています。

    • メモリ空間を作成します。

    • #オブジェクト Singleton をメモリ空間で初期化します。

    • #メモリ アドレスをインスタンス オブジェクトに割り当てます (この手順を実行すると、インスタンスは null に等しくなくなります)。

    想像してみてください。

    volatile が追加されていない場合、スレッド 1 は上記のコードの②を実行するときに命令の並べ替えを実行し、元の実行順序を変更する可能性があります。 1、2、3 を 1、3、2 に並べ替えます。ただし、特殊な状況では、スレッド 1 がステップ 3 を実行した後、スレッド 2 が来て上記のコードの最初のステップを実行すると、インスタンス オブジェクトは null ではないが、スレッド 1 はまだオブジェクトのインスタンス化を完了していないと判断されます。スレッド 2 はインスタンス化された「半分」のオブジェクトを取得し、プログラム実行エラーが発生するため、プライベート変数に volatile が追加されます。

    以上がJava シングルトン モードに volatile キーワードを追加する必要があるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    声明
    この記事は亿速云で複製されています。侵害がある場合は、admin@php.cn までご連絡ください。
    高度なJavaプロジェクト管理、自動化の構築、依存関係の解像度にMavenまたはGradleを使用するにはどうすればよいですか?高度なJavaプロジェクト管理、自動化の構築、依存関係の解像度にMavenまたはGradleを使用するにはどうすればよいですか?Mar 17, 2025 pm 05:46 PM

    この記事では、Javaプロジェクト管理、自動化の構築、依存関係の解像度にMavenとGradleを使用して、アプローチと最適化戦略を比較して説明します。

    適切なバージョン化と依存関係管理を備えたカスタムJavaライブラリ(JARファイル)を作成および使用するにはどうすればよいですか?適切なバージョン化と依存関係管理を備えたカスタムJavaライブラリ(JARファイル)を作成および使用するにはどうすればよいですか?Mar 17, 2025 pm 05:45 PM

    この記事では、MavenやGradleなどのツールを使用して、適切なバージョン化と依存関係管理を使用して、カスタムJavaライブラリ(JARファイル)の作成と使用について説明します。

    カフェインやグアバキャッシュなどのライブラリを使用して、Javaアプリケーションにマルチレベルキャッシュを実装するにはどうすればよいですか?カフェインやグアバキャッシュなどのライブラリを使用して、Javaアプリケーションにマルチレベルキャッシュを実装するにはどうすればよいですか?Mar 17, 2025 pm 05:44 PM

    この記事では、カフェインとグアバキャッシュを使用してJavaでマルチレベルキャッシュを実装してアプリケーションのパフォーマンスを向上させています。セットアップ、統合、パフォーマンスの利点をカバーし、構成と立ち退きポリシー管理Best Pra

    キャッシュや怠zyなロードなどの高度な機能を備えたオブジェクトリレーショナルマッピングにJPA(Java Persistence API)を使用するにはどうすればよいですか?キャッシュや怠zyなロードなどの高度な機能を備えたオブジェクトリレーショナルマッピングにJPA(Java Persistence API)を使用するにはどうすればよいですか?Mar 17, 2025 pm 05:43 PM

    この記事では、キャッシュや怠zyなロードなどの高度な機能を備えたオブジェクトリレーショナルマッピングにJPAを使用することについて説明します。潜在的な落とし穴を強調しながら、パフォーマンスを最適化するためのセットアップ、エンティティマッピング、およびベストプラクティスをカバーしています。[159文字]

    Javaのクラスロードメカニズムは、さまざまなクラスローダーやその委任モデルを含むどのように機能しますか?Javaのクラスロードメカニズムは、さまざまなクラスローダーやその委任モデルを含むどのように機能しますか?Mar 17, 2025 pm 05:35 PM

    Javaのクラスロードには、ブートストラップ、拡張機能、およびアプリケーションクラスローダーを備えた階層システムを使用して、クラスの読み込み、リンク、および初期化が含まれます。親の委任モデルは、コアクラスが最初にロードされ、カスタムクラスのLOAに影響を与えることを保証します

    See all articles

    ホットAIツール

    Undresser.AI Undress

    Undresser.AI Undress

    リアルなヌード写真を作成する AI 搭載アプリ

    AI Clothes Remover

    AI Clothes Remover

    写真から衣服を削除するオンライン AI ツール。

    Undress AI Tool

    Undress AI Tool

    脱衣画像を無料で

    Clothoff.io

    Clothoff.io

    AI衣類リムーバー

    AI Hentai Generator

    AI Hentai Generator

    AIヘンタイを無料で生成します。

    ホットツール

    MinGW - Minimalist GNU for Windows

    MinGW - Minimalist GNU for Windows

    このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

    mPDF

    mPDF

    mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。

    Safe Exam Browser

    Safe Exam Browser

    Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

    SublimeText3 英語版

    SublimeText3 英語版

    推奨: Win バージョン、コードプロンプトをサポート!

    SublimeText3 Mac版

    SublimeText3 Mac版

    神レベルのコード編集ソフト(SublimeText3)