ホームページ  >  記事  >  Java  >  Javaダブルチェックロックモードとは何ですか

Javaダブルチェックロックモードとは何ですか

WBOY
WBOY転載
2023-05-19 15:29:491465ブラウズ

原因

プロジェクトで PMD 静的コード検出を実行しているときにこのような問題が発生しました

部分的に作成されたオブジェクトは、使用時にダブル チェック ロック パターンによって返される可能性があります最適化 JRE は、参照が指すオブジェクトのコンストラクターを呼び出す前に、baz 変数への参照を割り当てることができます。

注: Java 5 では、次のように宣言すると、二重チェックされたロックを機能させることができます

#ダブルチェック ロック モードを使用すると、不完全に初期化されたオブジェクトが返される可能性があります。部分的に初期化されたオブジェクトの概念に疑問を持つ人もいるかもしれません。分析を続けてください。

二重チェック ロック モードとは

<code>public static Singleton getSingleton() {<br>    if (instance == null) {                        <br>        synchronized (Singleton.class) {<br>            if (instance == null) {                 <br>                instance = new Singleton();<br>            }<br>        }<br>    }<br>    return instance ;<br>}</code> 

同期されたコード ブロックの内側と外側の両方で、インスタンス = と判断されることがわかります。 = null の場合、同期コードブロック外で複数のスレッドが同時に if 判定に入る可能性があるためであり、同期コードブロック内で null 判定を行わないと複数のインスタンスが初期化される可能性があります。

問題点

この書き方は完璧に見えますが、問題があるか、完璧であることを保証するものではありません。主な理由は、instance = new Singleton(); がアトミックな操作ではないことです。

オブジェクトの作成は 3 つの部分に分けることができます:

<code>1.分配对象的内存空间<br>2.初始化对象<br>3.设置instance指向刚分配的内存地址<br>当instance指向分配地址时,instance是不为null的</code> 
ただし、ステップ 2 と 3 の間で順序が変更され、オブジェクトの作成順序が 1-3-2 になる場合があります。 :

スレッド A が初めてオブジェクト Singleton を作成し、オブジェクトの作成順序は 1-3-2 です;
インスタンスにメモリを割り当てた後、スレッド B が来て getSingleton() メソッドを呼び出します
This インスタンス == null 判定の場合、インスタンスは null ではないことがわかります。
ただし、この時点ではインスタンスはオブジェクトを初期化しておらず、スレッド B は初期化されていないオブジェクトを返すことに注意してください。スレッド B がインスタンスを使用するときに問題が発生する場合がありますが、これは二重チェック ロックの問題です。

volatile を使用する

上記の問題については、インスタンスを volatile として宣言することで上記の問題を解決できます

<code>public class Singleton{<br>    private volatile static Singleton instance;<br>    public static Singleton getSingleton() {<br>        if (instance == null) {                        <br>            synchronized (Singleton.class) {<br>                if (instance == null) {                 <br>                    instance = new Singleton();<br>                }<br>            }<br>        }<br>        return instance ;<br>    }<br>}</code> 
ただし、JDK5 バージョン以降で使用する必要があります。

静的内部クラス

<code>public class Singleton {  <br>    private static class SingletonHolder {  <br>        private static final Singleton INSTANCE = new Singleton();  <br>    }  <br>    private Singleton (){}  <br>    public static final Singleton getInstance() {  <br>        return SingletonHolder.INSTANCE; <br>    }  <br>}</code>

現在推奨されている記述方法は、スレッド安全性の問題を発生させずに遅延読み込みを実現できる静的内部クラスを使用することです。また、同期のオーバーヘッドも軽減されます。

以上がJavaダブルチェックロックモードとは何ですかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。