考慮下面的代碼
public static Singleton getInstance()
{
if (instance == null)
{
synchronized(Singleton.class) { //1
if (instance == null) //2
instance = new Singleton(); //3
}
}
return instance;
}
背後雙重檢查鎖定理論是第二檢查在// 2使得它不可能用於兩個不同的Singleton對象作爲發生清單
考慮以下的事件序列中創建:
線程1進入getInstance()方法。
線程1在// 1處進入同步塊,因爲實例爲空。
線程1被線程2
線程2進入getInstance()方法搶佔。
線程2嘗試獲取// 1處的鎖,因爲實例仍爲空。但是,因爲線程1保持鎖定,所以線程2在// 1處阻塞。
線程2被線程1
線程佔先1個執行並因爲實例仍然空在// 2,創建一個Singleton對象並分配其參考實例。
線程1退出synchronized塊並從getInstance()方法返回實例。
線程1是由線程搶佔2.
線程2在// 1,並檢查獲得鎖,以查看是否實例爲null。
由於實例非空,因此不會創建第二個Singleton對象,並返回由線程1創建的對象。
雙重鎖定鎖定理論是完美的。不幸的是,現實是完全不同的。雙重檢查鎖定的問題是不能保證它可以在單處理器或多處理器的機器上工作。 雙重檢查鎖定失敗的問題不是由於JVM中的實現錯誤,而是由於當前的Java平臺內存模型。內存模型允許所謂的「無序寫入」,這是這個習慣用法失敗的主要原因。
看到這個偉大的職位雙重檢查單身人士:http://www.ibm.com/developerworks/java/library/j-dcl/index.html – 2012-08-08 16:38:30
雙重檢查鎖定習語的主要缺點:它是壞的,除非你讓道易變。不要使用它。 – assylias 2012-08-08 16:54:46