Java多線程(2)——單例模式

首先,介紹一下單例模式:

在Java應用中,單例對象能保證在一個JVM中,該對象只有一個實例存在。

正是由於這個特點,單例對象通常作爲程序中的存放配置信息的載體,因爲它能保證其他對象讀到一致的信息。例如在

某個服務器程序中,該服務器的配置信息可能存放在數據庫或 文件中,這些配置數據由某個單例對象統一讀取,服務進程中的其他對象如果要獲取這些配置信息,只需訪問該單例對象即可。這種方式極大地簡化了在複雜環境 下,尤其是多線程環境下的配置管理,但是隨着應用場景的不同,也可能帶來一些同步問題。

單例模式的兩種實現方式:

第一種方式:餓漢式,使用static final修飾單例

 
//餓漢式,靜態初始化創建好實例
class Single{
	private static final Single s = new Single();
	private Single();
	public static Single getInstance(){
			return s;
		}
	}

第二種方式:懶漢式,需使用同步保證單例的唯一性

//懶漢式
class SingleLazy{
	private static SingleLazy s = null;
	private SingleLazy(){}
	public static SingleLazy getInstance(){
		if(s==null){
				synchronized(SingleLazy.class){
						if(s==null)
						       s= new SingleLazy();
					}
			}
		}
	}

我們會發現在使用懶漢式的時候使用同步機制,會造成線程的長時間等待,效率不高。這時候聰明的程序猿們使用了雙重校驗鎖。

下列論述摘自:http://www.ibm.com/developerworks/cn/java/j-dcl.html  (大家可以看看這篇文章,寫的非常好)

雙重檢查鎖定失敗的問題並不歸咎於 JVM 中的實現 bug,而是歸咎於 Java 平臺內存模型。內存模型允許所謂的“無序寫入”,這也是這些習語失敗的一個主要原因。


我們這裏只做結論:

爲避免單例中代價高昂的同步,程序員非常聰明地發明了雙重檢查鎖定習語。不幸的是,鑑於當前的內存模型的原因,該習語尚未得到廣泛使用,就明顯成爲了一種不安全的編程結構。重定義脆弱的內存模型這一領域的工作正在進行中。儘管如此,即使是在新提議的內存模型中,雙重檢查鎖定也是無效的。對此問題最佳的解決方案是接受同步或者使用一個 static field




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章