シングルケースモード(Head First版)

2045 ワード

≪単一モード|Single Mode|emdw≫:クラスにインスタンスが1つしかないことを確認し、グローバル・アクセス・ポイントを提供します.
コード実装:
package com.headfirst.chapter5;

public class Singleton {
	private static Singleton singleton;
	private Singleton(){}
	public static Singleton getInstance(){
		if(singleton == null){
			singleton = new Singleton();
		}
		return singleton;
	}
}

 
 
上記の例では,高同時の場合,2つのインスタンスが生成される可能性が高い.
スレッドがsingleton=new Singleton()に入り、まだインスタンス化されていません.
もう1つのスレッドはsingleton==nullでtrueです.これにより2つのインスタンスが生成されます
上のgetInstanceメソッドに同期ブロックを追加します.次のように
 
package com.headfirst.chapter5;

public class Singleton {
	private static Singleton singleton;
	private Singleton(){}
	public static synchronized Singleton getInstance(){
		if(singleton == null){
			singleton = new Singleton();
		}
		return singleton;
	}
}


これにより、1つのインスタンスのみが生成されることが保証されますが、高同時性の場合、この方法はパフォーマンスに問題があります.
修正を続けsingleton変数にvolatile修飾を加える
また、同期ブロックは、最初のインスタンス化時にのみ入力され、同期のパフォーマンスの問題が解決されます.
 
package com.headfirst.chapter5;

public class Singleton {
  private volatile static Singleton singleton;
  private Singleton(){}
  public static Singleton getInstance(){
  if(singleton == null){
     synchronized(Singleton.class){
       if(singleton == null){
          singleton = new Singleton();
       }
      }
   }
   return singleton;
}

 
なぜsingletonをグローバルな静的変数として定義しないのか、以下のようにします.
public static Singleton singleton = new Singleton();
このように書くと,Singletonが初期化されると,この変数はインスタンス化され,すなわち急に確実にインスタンス化される.
上記の例とは異なり、この変数を実際に使用した場合にのみインスタンス化されます.
Volatile変数はsynchronizedの可視性特性を持つが,原子特性は備えていない.すなわち、スレッドはvolatile変数の最新値を自動的に発見することができる.
volatileの使用には明確な規定があります.
変数の書き込み操作は現在の値に依存しません.
この変数は、他の変数を有する不変式に含まれていない.