天天看點

Java并發程式設計中雙重檢查鎖漏洞

單例模式在實際工作或面試中出現的頻率更高,double-checked lock是單例常見實作:

<b>public</b> <b>class</b> SimpleSingleton4 {

    <b>private</b> <b>static</b> SimpleSingleton4 INSTANCE;

    <b>private</b> SimpleSingleton4() {
    }

    <b>public</b> <b>static</b> SimpleSingleton4 getInstance() {
        <b>if</b> (INSTANCE == <b>null</b>) {
            <b>synchronized</b> (SimpleSingleton4.<b>class</b>) {
                <b>if</b> (INSTANCE == <b>null</b>) {
                    INSTANCE = <b>new</b> SimpleSingleton4();
                }
            }
        }
        <b>return</b> INSTANCE;
    }
}      

這段代碼有問題:

<b>public</b> <b>static</b> SimpleSingleton4 getInstance() {
    <b>if</b> (INSTANCE == <b>null</b>) {<font><i>//1</i></font><font>
        <b>synchronized</b> (SimpleSingleton4.<b>class</b>) {</font><font><i>//2</i></font><font>
            <b>if</b> (INSTANCE == <b>null</b>) {</font><font><i>//3</i></font><font>
                INSTANCE = <b>new</b> SimpleSingleton4();</font><font><i>//4</i></font><font>
            }
        }
    }
    <b>return</b> INSTANCE;</font><font><i>//5</i></font><font>
}
</font>      

你希望按1, 2, 3, 4, 金額 5順序執行。

但是Java虛拟機實際上會做一些優化,重新排列一些代碼指令。重排後的順序可能會變成: 1, 3, 2, 4, 5,這樣在多線程的情況下也會建立多個執行個體。重新排列的代碼可能如下所示:

<b>public</b> <b>static</b> SimpleSingleton4 getInstance() {
    <b>if</b> (INSTANCE == <b>null</b>) {<font><i>//1</i></font><font>
       <b>if</b> (INSTANCE == <b>null</b>) {</font><font><i>//3</i></font><font>
           <b>synchronized</b> (SimpleSingleton4.<b>class</b>) {</font><font><i>//2</i></font><font>
                INSTANCE = <b>new</b> SimpleSingleton4();</font><font><i>//4</i></font><font>
            }
        }
    }
    <b>return</b> INSTANCE;</font><font><i>//5</i></font><font>
}
</font>      

有什麼解決辦法?

答:您可以将volatile關鍵字添加到 的定義中INSTANCE。具體代碼如下:

<b>private</b> <b>volatile</b> <b>static</b> SimpleSingleton7 INSTANCE;

<b>private</b> SimpleSingleton7() {
}

<b>public</b> <b>static</b> SimpleSingleton7 getInstance() {
    <b>if</b> (INSTANCE == <b>null</b>) {
        <b>synchronized</b> (SimpleSingleton7.<b>class</b>) {
            <b>if</b> (INSTANCE == <b>null</b>) {
                INSTANCE = <b>new</b> SimpleSingleton7();
            }
        }
    }
    <b>return</b> INSTANCE;
}      

繼續閱讀