單例模式 從不好到完美

2021-10-07 12:46:49 字數 1935 閱讀 9665

單例模式的定義:確保某乙個類只有乙個例項,而且這個類可以自行例項化,並向整個系統提供這個例項。

最最簡單的方法(餓漢模式):

public class singleton 

// 通過該方法獲取例項物件

public static singleton getsingleton()

// 類中的其它方法盡量是static

public static void dosomething()

}

最最簡單的方法(懶漢模式):執行緒不安全

問題:1. 如果乙個執行緒a執行到singleton = new singleton(),但是還沒獲取物件,第二個執行緒b也在執行,執行到(singleton == null)判斷,那麼執行緒b判斷為真,於是繼續執行,那麼就會導致在記憶體**現兩個重複的物件。

2. 如果有n多個執行緒,每次執行到物件賦值操作的時候時間片就到了,那麼就會有很多執行緒都判斷singleton為null,所以產生好多物件例項,從而導致sinleton被多次賦值,最後return的時候也會返回不同的位址的例項物件。

解決辦法:使用synchronized對方法進行加鎖

public class singleton 

// 通過該方法獲取例項物件

public static singleton getsingleton()

return singleton;

}}

優化後的單例模式(對整個**塊進行加鎖):

優點:簡單粗暴,直接給把整個方法加鎖

缺點:鎖粒度太大,導致效率過低

public class singleton 

// 通過該方法獲取例項物件

public static synchronized singleton getsingleton()

return singleton;

}}

再次優化,只對建立物件的部分進行加鎖:

那麼問題又來了,看波浪線那裡,如果多個執行緒都跑到波浪線那裡了,在每個執行緒拿到鎖之後還是會進行多次賦值,所以還需要再優化,。

public class singleton 

// 通過該方法獲取例項物件

public static singleton getsingleton()

}return singleton;

}}

再優化:

改進點:再加一層判空。當乙個執行緒拿到鎖,再釋放鎖,那麼物件必定已經例項化,其它執行緒再拿到鎖的時候也必須再次判空,再判空的時候就發現變數已經被賦值,所以就退出返回

新問題:

再new乙個物件的時候,會走以下過程,但是這三條指令也許會亂序執行,正常是123,亂序執行是132,因此如果執行緒a執行完13,時間片就到了,那麼執行緒b進來發現變數已經不為空,所以就會返回乙個沒有進行第二步,即未進行初始化操作的物件,最後導致出錯。

1.給singletonlazy5的例項分配記憶體。

2.初始化singletonlazy5的構造器

3.將singletonlazy物件指向分配的記憶體空間(注意到這步instance就非null了)。

public class singleton 

// 通過該方法獲取例項物件

public static singleton getsingleton() }}

return singleton;

}}

終極方案:使用volatile防止重排序

public class singleton 

// 通過該方法獲取例項物件

public static singleton getsingleton() }}

return singleton;

}}

完美的單例模式

一 立即載入模式 餓漢模式 立即載入模式 餓漢模式 author lzn public class singleone 該方法保證在多執行緒中獲取的是同乙個物件 該方法缺點是不能有其他例項變數,因為getinstance 不是同步方法,會引起執行緒安全問題 return public static ...

單例模式 單例模式

餓漢式 急切例項化 public class eagersingleton 2.宣告靜態成員變數並賦初始值 類初始化的時候靜態變數就被載入,因此叫做餓漢式 public static eagersingleton eagersingleton new eagersingleton 3.對外暴露公共的...

ios下比較完美的單例模式

網上關於ios單例模式實現的帖子已經很多了,有很多版本,裡面有對的也有不對的。我在使用過程中很難找到乙個比較完美的方法,索性自己寫乙個吧,經過專案驗證是比較合理的乙個版本。static prautologinview s sharedinstance nil prautologinview shar...