單例模式和執行緒安全問題

2021-10-23 15:28:59 字數 2405 閱讀 9755

單例模式是一種常用的軟體設計模式,其定義是單例物件的類只能允許乙個例項存在。

​ 許多時候整個系統只需要擁有乙個的全域性物件,這樣有利於我們協調系統整體的行為。比如在某個伺服器程式中,該伺服器的配置資訊存放在乙個檔案中,這些配置資料由乙個單例物件統一讀取,然後服務程序中的其他物件再通過這個單例物件獲取這些配置資訊。這種方式簡化了在複雜環境下的配置管理。

單例模式要求類能夠有返回物件乙個引用(永遠是同乙個)和乙個獲得該例項的方法(必須是靜態方法,通常使用getinstance這個名稱)。

單例的實現主要是通過以下兩個方式:

將該類的構造方法定義為私有方法,這樣其他處的**就無法通過呼叫該類的構造方法來例項化該類的物件,只有通過該類提供的靜態方法來得到該類的唯一例項;

在該類內提供乙個靜態方法,當我們呼叫這個方法時,如果類持有的引用不為空就返回這個引用,如果類保持的引用為空就建立該類的例項並將例項的引用賦予該類保持的引用。

餓漢模式

public

class

ehan

//靜態變數建立物件

private

static ehan instance=

newehan()

;//對外提供獲取物件的方法

public

static ehan getinstance()

}

懶漢模式

public

class

lanhan

;//建立物件

private

static lanhan instance=null;

//對外提供靜態訪問方法,獲取本類例項物件

public

static lanhan getinstance()

return instance;

}}

懶漢模式,它的特點是執行時獲得物件的速度比較慢,但載入類的時候比較快。它在整個應用的生命週期只有一部分時間在占用資源

餓漢模式,它的特點是載入類的時候比較慢,但執行時獲得物件的速度比較快。它從載入到應用結束會一直占用資源

這兩種模式對於初始化較快,占用資源少的輕量級物件來說,沒有多大的效能差異,選擇懶漢式還是餓漢式都沒有問題。但是對於初始化慢,占用資源多的重量級物件來說,就會有比較明顯的差別了。所以,對重量級物件應用餓漢模式,類載入時速度慢,但執行時速度快;懶漢模式則與之相反,類載入時速度快,但執行 時第一次獲得物件的速度慢。

從使用者體驗的角度來說,我們應該首選餓漢模式。我們願意等待某個程式花較長的時間初始化,卻不喜歡在程式執行時等待太久,給人一種反應遲鈍的感覺,所以對於有重量級物件參與的單例模式,我們推薦使用餓漢模式

//餓漢式 多執行緒併發餓漢式沒問題。多執行緒在執行getinstance()方法時不進行物件的建立。

class

single

public

static single getinstance()

}//懶漢式。

class

single

/* 併發訪問會有安全隱患,多個執行緒可能同時進行if(s==null)判斷並建立多個對線,所以加入同步機制 解決安全問題。

但是,同步的出現降低了效率。

可以通過雙重判斷的方式,解決效率問題,減少判斷鎖的次數。

*/public

static single getinstance()

}return s;

}}

​ 當s == null時,a執行緒進來了,它加了一下鎖後進入第二個if(s ==null){},然後沉睡;此時,b也通過了第乙個 if(s == null),當b玩下執行時,遇到了synchronized(),發現這裡a進行了加鎖,沒辦法b執行緒只能等著,等a把鎖解了。此時,a執行緒醒來了,它new 了乙個物件後,繼續玩下執行,然後把鎖解了,這時s不等於null了。b發現a解鎖了,它繼續往下執行,發現s不等於null了,那它直接返回了a建立的那個物件s。當c執行緒訪問getsingle方法時,只需判斷s是否為null,而不用去判斷鎖物件了。因為s不等於null了,所以直接返回物件,這樣就提高了效率。

懶漢模式是延遲載入的例項,面對多執行緒訪問時,需要進行同步**塊,為了增加效率,又要使用雙重判斷

如果沒有第乙個if,那麼多執行緒訪問時,每個執行緒都需要去判斷鎖,而雙重判斷模式下,更多機會只需判斷if條件,相比較判斷鎖更有效率

單例模式及執行緒安全問題

單例模式是為確保乙個類只有乙個例項,並為整個系統提供乙個全域性訪問點的一種模式方法。從概念中體現出了單例的一些特點 1 在任何情況下,單例類永遠只有乙個例項存在 2 單例需要有能力為整個系統提供這一唯一例項 下面是實現 package org.mlinge.s02 public class mysi...

單例模式的執行緒安全問題

單例會帶來什麼問題?如果多個執行緒同時呼叫這個例項,會有執行緒安全的問題 單例一般用在什麼地方?單例的目的是為了保證執行時只有唯一的乙個例項,最常用的地方比如拿到資料庫的連線,或者spring的中建立beanfactory操作,而這些操作都是呼叫他們的方法來執行某個特定的動作。首先先來認識下兩種模式...

單例模式的執行緒安全問題

大家都知道單例模式有兩種,分別是懶漢式 餓漢式。但是對於餓漢式,由於判斷例項為null與建立物件的操作並不是乙個原子性操作,故在 普通的懶漢式單例 非執行緒安全問題 1 2 created by ywb 3 4public class singleton 910 public static sing...