單例模式要求實現的目標:保持乙個類有且僅有乙個例項,單例模式一般會採用延遲載入的模式
public
class
singlethreadedsingleton
public
static singlethreadsingleton getinstance()
return instance;
}public
void
someservice()
}
在多執行緒環境下,getinstance()中的if語句形成乙個 check-then-act 操作,它不是乙個原子操作,**中為使用任何同步機制,因此該程式的執行可能出現交錯的情形,在instance值還是null的時候,執行緒t1和t2同時執行到操作1接著在t1執行操作2前t2億率先執行完操作2.當t1執行到操作1時,instance為null,這就導致了多個例項的建立,從而違背了初衷。
可以通過加鎖實現的單例模式
public
class
******multithreadedsingleton
public
static simjplemultithreadedsingleton getinstance()
return instance;
}public
void
someservice()
}}
該方法實現的單例模式固然是執行緒安全的,但是這意味著getinstance()的任何乙個執行執行緒都需要申請鎖。這會造成很大的開銷。為了避免這種情況,可以在執行臨界區前先進性一次instance是否為null的檢查,如果不為null 那麼直接返回 instance,如果為null,加執行鎖,在鎖中進行操作,因此他被稱為雙重檢查鎖定。
public
class
******multithreadedsingleton
public
static simjplemultithreadedsingleton getinstance()
}}return instance;
public
void
someservice()
}}
但是這同樣還是有問題的,根據例項化類的流程操作3可以分解為以下子步驟
objref = allocate(incorrectdclsingletion.class); // 1. 分配物件所需的儲存空間
invokeconstructor(objref);// 2. 初始化objref引用的物件
instance = objref// 3. 將物件引用共享變數
根據所得重排序規則,臨界區內的操作可以在臨界區內被重排序,因此,jit編譯器可能將上述操作的順序交換,可能會被使用132,在初始化物件之前將物件的引用寫入例項變數,這使得另乙個執行緒可能可能看到乙個未初始化完畢的例項,即變數instance的值不為null,但是該變數所引用的物件中的某些例項變數的變數值可能仍然為預設值,而不是構造器中設定的初始值。
我們可以利用volatile關鍵字的一下兩個作用。
通過volatile 關鍵字對上述兩點的保障,
public
class
******multithreadedsingleton
public
static simjplemultithreadedsingleton getinstance()
}}return instance;
public
void
someservice()
}}
設計模式4 單例模式
保證乙個類僅有乙個例項,並提供乙個訪問他的全域性訪問點。所有類都有構造方法,假如不對他進行編碼,系統會生成空的public 的構造方法,外部類就能建立這個類的物件。為了不讓其他類能new出這個類的例項,所以需要寫乙個private 的構造方法 其實即使使用private修飾,通過反射機制還是能在外部...
設計模式 4 單例模式
單例模式屬於建立型的設計模式,其特點是在於保證乙個類只會被例項化一次,可以作為全域性唯一資源提供給系統。此處通過判斷兩個例項的位址是否一致來驗證單例模式,中包含了保證多執行緒安全的單例模式實現。由於python下的懶漢單例模式實現本人覺得是不可能的,因此下面使用了double check的方式實現了...
設計模式 4 單例模式
單例模式用來確保乙個類只有乙個例項,並提供乙個全域性訪問點。在所有的設計模式中,單例模式是最簡單也是最常用的一種設計模式,它只為乙個例項提供乙個全域性物件,內次嘗試去獲取乙個類的例項的時候,保證獲取到的都是這乙個物件。下面是關於單例模式中的一些小概念 餓漢式和懶漢式區別 餓漢就是類一旦載入,就把單例...