程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA編程入門知識 >> 線程安全的單例模式的幾種實現方法分享

線程安全的單例模式的幾種實現方法分享

編輯:JAVA編程入門知識

1、餓漢式單例

代碼如下:

public class Singleton {
   private final static Singleton INSTANCE = new Singleton();

   private Singleton() { }

   public static Singleton getInstance() {
      return INSTANCE;
   }
}

2、借助內部類
屬於懶漢式單例,因為Java機制規定,內部類SingletonHolder只有在getInstance()方法第一次調用的時候才會被加載(實現了lazy),而且其加載過程是線程安全的。內部類加載的時候實例化一次instance。

代碼如下:

public class Singleton {

   private Singleton() { }

   private static class SingletonHolder {
      private final static Singleton INSTANCE = new Singleton();
   }

   public static Singleton getInstance() {
      return SingletonHolder.INSTANCE;
   }
}

3、普通加鎖解決

代碼如下:

public class Singleton {
   private static Singleton instance = null;

   private Singleton() { }

   public static synchronized Singleton getInstance() {
      if(instance == null) {
         instance = new Singleton();
      }

      return instance;
   }
}

雖然解決了線程安全問題,但是每個線程調用getInstance都要加鎖,我們想要只在第一次調用getInstance時加鎖,請看下面的雙重檢測方案

4、雙重檢測,但要注意寫法

代碼如下:

public class Singleton {
   private static Singleton instance = null;

   private Singleton() { }

   public static Singleton getInstance() {
      if(instance == null) {
         synchronzied(Singleton.class) {
            Singleton temp = instance;
            if(temp == null) {
               temp = new Singleton();
               instance = temp
            }
         }
      }

      return instance;
   }
}

由於指令重排序問題,所以不可以直接寫成下面這樣:
public class Singleton {
   private static Singleton instance = null;

   private Singleton() { }

   public static Singleton getInstance() {
      if(instance == null) {
         synchronzied(Singleton.class) {
            if(instance == null) {
               instance = new Singleton();
            }
         }
      }

      return instance;
   }
}

但是如果instance實例變量用volatile修飾就可以了,volatile修飾的話就可以確保instance = new Singleton();對應的指令不會重排序,如下的單例代碼也是線程安全的:
public class Singleton {
   private static volatile Singleton instance = null;

   private Singleton() { }

   public static Singleton getInstance() {
      if(instance == null) {
         synchronzied(Singleton.class) {
            if(instance == null) {
               instance = new Singleton();
            }
         }
      }

      return instance;
   }
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved