高併發環境下執行緒安全的單例模式(最全最經典)
在所有的設計模式中,單例模式是我們在專案開發中最為常見的設計模式之一,而單例模式有很多種實現方式,你是否都瞭解呢?高併發下如何保證單例模式的執行緒安全性呢?如何保證序列化後的單例物件在反序列化後任然是單例的呢?這些問題在看了本文之後都會一一的告訴你答案,趕快來閱讀吧!
什麼是單例模式?
在文章開始之前我們還是有必要介紹一下什麼是單例模式。單例模式是為確保一個類只有一個例項,併為整個系統提供一個全域性訪問點的一種模式方法。
從概念中體現出了單例的一些特點:
(1)、在任何情況下,單例類永遠只有一個例項存在
(2)、單例需要有能力為整個系統提供這一唯一例項
為了便於讀者更好的理解這些概念,下面給出這麼一段內容敘述:
在計算機系統中,執行緒池、快取、日誌物件、對話方塊、印表機、顯示卡的驅動程式物件常被設計成單例。這些應用都或多或少具有資源管理器的功能。每臺計算機可以有若干個印表機,但只能有一個Printer Spooler,以避免兩個列印作業同時輸出到印表機中。每臺計算機可以有若干通訊埠,系統應當集中管理這些通訊埠,以避免一個通訊埠同時被兩個請求同時呼叫。總之,選擇單例模式就是為了避免不一致狀態,避免政出多頭。
正是由於這個特點,單例物件通常作為程式中的存放配置資訊的載體,因為它能保證其他物件讀到一致的資訊。例如在某個伺服器程式中,該伺服器的配置資訊可能存放在資料庫或檔案中,這些配置資料由某個單例物件統一讀取,服務程序中的其他物件如果要獲取這些配置資訊,只需訪問該單例物件即可。這種方式極大地簡化了在複雜環境 下,尤其是多執行緒環境下的配置管理,但是隨著應用場景的不同,也可能帶來一些同步問題。
各式各樣的單例實現
溫馨提示:本文敘述中涉及到的相關原始碼可以在這裡進行下載原始碼,讀者可免積分下載。
1、餓漢式單例
餓漢式單例是指在方法呼叫前,例項就已經建立好了。下面是實現程式碼:
- package org.mlinge.s01;
- publicclass MySingleton {
- privatestatic MySingleton instance = new MySingleton();
- private MySingleton(){}
- publicstatic MySingleton getInstance() {
- return instance;
- }
- }
- package org.mlinge.s01;
- publicclass MyThread extends Thread{
- @Override
- publicvoid run() {
- System.out.println(MySingleton.getInstance().hashCode());
- }
- publicstaticvoid main(String[] args) {
- MyThread[] mts = new MyThread[10];
- for(int i = 0 ; i < mts.length ; i++){
- mts[i] = new MyThread();
- }
- for (int j = 0; j < mts.length; j++) {
- mts[j].start();
- }
- }
- }
以上程式碼執行結果:
- 1718900954
- 1718900954
- 1718900954
- 1718900954
- 1718900954
- 1718900954
- 1718900954
- 1718900954
- 1718900954
- 1718900954
從執行結果可以看出例項變數額hashCode值一致,這說明物件是同一個,餓漢式單例實現了。
2、懶漢式單例
懶漢式單例是指在方法呼叫獲取例項時才建立例項,因為相對餓漢式顯得“不急迫”,所以被叫做“懶漢模式”。下面是實現程式碼:
- package org.mlinge.s02;
- publicclass MySingleton {
- privatestatic MySingleton instance = null;
- private MySingleton(){}
- publicstatic MySingleton getInstance() {
- if(instance == null){//懶漢式
- instance = new MySingleton();
- }
- return instance;
- }
- }
- package org.mlinge.s02;
- publicclass MySingleton {
- privatestatic MySingleton instance = null;
- private MySingleton(){}
- publicstatic MySingleton getInstance() {
- try {
- if(instance != null){//懶漢式
- }else{
- //建立例項之前可能會有一些準備性的耗時工作
- Thread.sleep(300);
- instance = new MySingleton();
- }
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- return instance;
- }
- }
- package org.mlinge.s02;
- publicclass MyThread extends Thread{
- @Override
- publicvoid run() {
- System.out.println(MySingleton.getInstance().hashCode());
- }
- publicstaticvoid main(String[] args) {
- MyThread[] mts = new MyThread[10];
- for(int i = 0 ; i < mts.length ; i++){
- mts[i] = new MyThread();
- }
- for (int j = 0; j < mts.length; j++) {
- mts[j].start();
- }
- }
- }
執行結果如下:
- 1210420568
- 1210420568
- 1935123450
- 1718900954
- 1481297610
- 1863264879
- 369539795
- 1210420568
- 1210420568
- 602269801
從這裡執行結果可以看出,單例的執行緒安全性並沒有得到保證,那要怎麼解決呢?
3、執行緒安全的懶漢式單例
要保證執行緒安全,我們就得需要使用同步鎖機制,下面就來看看我們如何一步步的解決 存線上程安全問題的懶漢式單例(錯誤的單例)。
(1)、 方法中宣告synchronized關鍵字
出現非執行緒安全問題,是由於多個執行緒可以同時進入getInstance()方法,那麼只需要對該方法進行synchronized的鎖同步即可:
- package org.mlinge.s03;
- publicclass MySingleton {
- privatestatic MySingleton instance = null;
- private MySingleton(){}
- publicsynchronizedstatic MySingleton getInstance() {
- try {
- if(instance != null){//懶漢式
- }else{
- //建立例項之前可能會有一些準備性的耗時工作
-
相關推薦
高併發環境下執行緒安全的單例模式(最全最經典)
在所有的設計模式中,單例模式是我們在專案開發中最為常見的設計模式之一,而單例模式有很多種實現方式,你是否都瞭解呢?高併發下如何保證單例模式的執行緒安全性呢?如何保證序列化後的單例物件在反序列化後任然是單例的呢?這些問題在看了本文之後都會一一的告訴你答案,趕快來閱讀吧!什麼是單
C++的單例模式與執行緒安全單例模式(懶漢/餓漢)
單例模式 單例模式:是一種常用的軟體設計模式。在它的核心結構中只包含一個被稱為單例的特殊類。通過單例模式可以保證系統中一個類只有一個例項。即一個類只有一個物件例項。 實現簡單的單例模式:建構函式宣告為private或protect防止被外部函式
[C++][執行緒安全]單例模式下雙檢查鎖和執行緒
問題 在設計模式中,有一個很經典的模式-單例模式,它可能是實現上最簡單的模式,在程式碼中也經常使用,在單執行緒下,毫無疑問延遲化載入是比較常用的,但是在多執行緒條件下,單例模式的延遲載入可能就會出現一些問題。 如以下的程式碼: T* GetInstance(
高併發程式設計:執行緒安全和ThreadLocal
執行緒安全的概念:當多個執行緒訪問某一個類(物件或方法)時,這個類始終都能表現出正確的行為,那麼這個類(物件或方法)就是執行緒安全的。 執行緒安全 說的可能比較抽象,下面就以一個簡單的例子來看看什麼是執行緒安全問題。 public class MyThread impleme
Java設計模式(二):單例模式的5種實現方式,以及在多執行緒環境下5種建立單例模式的效率
這段時間從頭溫習設計模式。記載下來,以便自己複習,也分享給大家。 package com.iter.devbox.singleton; /** * 餓漢式 * @author Shearer * */ public class SingletonDemo1 {
執行緒安全單例設計模式+序列化
懶漢式單例模式會引來執行緒安全問題,即多執行緒時可能會建立多個例項,而且在反序列化時也可能會建立新的例項。看了大大們的實現方式,覺得以下一種比較簡單方便理解。 一、下面是會造成執行緒安全的餓漢單例模式。用四列印下會發現hashcode不一致 public class Singleton {
高效能的執行緒安全單例——Java基礎語法系列
大家都知道,一般實現單例有兩種寫法: 餓漢式 和 懶漢式, 餓漢式是執行緒安全的,在編譯期間已完成初始化,載入到了記憶體裡。 懶漢式一般寫法是非執行緒安全的, 那懶漢式的執行緒安全單例應該如何實現呢,以及如何寫出低耗能的執行緒安全單例呢 ? 單例實現關鍵點 建構函式私有,
Qt下實現支援多執行緒的單例模式
1. 程式碼介紹 實現單例模式的程式碼很多。 本文的單例模式實現程式碼是本人一直在工程專案中使用的,現拿出和大家交流分享。 本文實現的單例模式,支援多執行緒,採用雙重校驗檢索的方式,整合析構類,杜絕記憶體洩漏,穩定性好。 使用C++/Qt的朋友們可以瞭解一下。 不再廢話,直接上程式碼。
java通過雙重檢測或列舉類實現執行緒安全單例(懶漢模式)
雙重檢測實現 /** * 懶漢模式->雙重同步鎖單例模式 */ public class SingletonExample5 { private SingletonExample5() { } //volatile + 雙重檢測機制 -> 禁止指令重排序
執行緒安全(單例與多例)
又週五了,時間過得好快,住在集體宿舍,幾個宅男共處一室好是無聊,習慣性來到CSDN。今天一個應屆生同事突然問我為什麼老大要求我們不要在Service裡寫成員變數,說不安全,說為什麼不安全讓他自己去了解,看上去他沒有找到頭緒很是痛苦,想想當初這個問題也困擾過自己,向
執行緒涉及單例模式
/** * 單例模式涉及的兩個問題 * * @author 羅摩銜那 * */ /* * 惡漢式 * 優點:當類被載入的時候,已經建立好了一個靜態的物件,因此,是執行緒安全的 * 缺點:這個物件還沒有被使用就被創建出來了 */ class Single { private s
日常小結-多執行緒的單例模式的三種實現方式
多執行緒單例模式在很多併發的書裡面都有寫。這裡做一個簡單的總結。主要內容來自《java併發程式設計的藝術》《java多執行緒程式設計核心》 單例模式的分類 餓漢模式:類初始化的時候就進行建立單例模式 懶漢模式:在呼叫getinstance方法的時候才建
JAVA_多執行緒_單例模式
這篇是入職之後的第二篇了,上一篇我簡單介紹了一下LOCK裡面的類的方法,感興趣的話可以去了解一下,以後堅持每週至少會更新一篇關於多執行緒方面的文章,希望博友們可以一起加油成長。 這篇主要的內容是單例模式在多執行緒環境下的設計,這篇算是比較重要的內容,我會進行文字和程式碼的共同說明來講解記錄 1、立即載入(餓
【Java多執行緒】單例模式與多執行緒
單例模式大家都不陌生,即讓一個類只有一個例項。 單例模式分為懶漢式和餓漢式。 懶漢式☞方法呼叫時再例項化物件,什麼時候用什麼時候例項化,比較懶。 餓漢式☞方法呼叫前物件就已經建立好了,比較有捉急。 本文著重描述懶漢式與多執行緒的內容。 1.餓漢式 public
Java多執行緒之單例模式-yellowcong
我們常見的單利模式有餓漢式和懶漢式,懶漢式,就是在用的時候,再例項化物件,餓漢式,是還沒有開飯,就已經把物件例項化好了。在多執行緒開發中,解決單例的時候,有兩種解決方案,1、(懶漢式)同步程式碼塊
單例模式(懶漢,餓漢)
ati turn 還需 sin 有用 只需要 對象 clas main Java中的單例模式一般分為懶漢模式和餓漢模式,懶漢模式只有用得到的時候對象才初始化,餓漢模式無論用得到與否,都先初始化。 懶漢模式在運行的時候獲取對象比較慢(因為類加載時並沒有創建對象實例),但是加載
java單例模式(雙重檢查加鎖)的原因
csharp sta get 第一次 instance new 同步機制 原因 AR public class Singleton{ private static Singleton instance = null;//是否是final的不重要,因為最多只可能實
單例模式(餓漢式 & 懶漢式)
建立型模式——單例模式 -目的:使得類的一個物件成為該類系統中的唯一例項。 -定義:一個類有且僅有一個例項,並且自行例項化向整個系統提供。 優點: 1、在記憶體中只有一個物件,節省記憶體空間。 2、
C++實現一個單例模式(懶漢與餓漢)
單例模式的特點: 1、一個類只能有一個例項。 2、一個類必須自己建立自己的唯一例項。 3、一個類必須給所有其他物件提供這一例項。 單例模式的實現: 1、將建構函式宣告為private防止被外部
Java 單例模式(餓漢+懶漢)
java單例就是一個類始終只例項化一次 餓漢模式:在程式啟動,類載入的時候就初始化: public class Singleton{ private static Singleton instance = new Singleton(); private S