javaのシングルトンについて調べているのですが、疑問が浮かんだので質問をさせてください。
javaでスレッドセーフなシングルトンクラスを書く場合は下記のようなものになると思います(ソースはココから拾ってきました)。
java
1public class SingletonClass { 2 3 private static volatile SingletonClass sSoleInstance; 4 5 //private constructor. 6 private SingletonClass(){ 7 8 //Prevent form the reflection api. 9 if (sSoleInstance != null){ 10 throw new RuntimeException("Use getInstance() method to get the single instance of this class."); 11 } 12 } 13 14 public static SingletonClass getInstance() { 15 //Double check locking pattern 16 if (sSoleInstance == null) { //Check for the first time 17 18 synchronized (SingletonClass.class) { //Check for the second time. 19 //if there is no instance available... create new one 20 if (sSoleInstance == null) sSoleInstance = new SingletonClass(); 21 } 22 } 23 24 return sSoleInstance; 25 } 26}
ここで、SingletonClassに「必要なときだけ生成して、誰からも(どのスレッドからも)参照されなくなったら開放する」という振る舞いを持たせるために、開放用のrelease()
メソッドと参照カウンタを実装するとします。getInstance()
でオブジェクトを取得し、用が済んだらrelease()
します。どこからも参照されなくなった時点でsSoleInstance=null
をします。
java
1public class SingletonClass { 2 3 private static volatile SingletonClass sSoleInstance; 4 private static int refCounter = 0; // 参照カウンター 5 6 //private constructor. 7 private SingletonClass(){ 8 9 //Prevent form the reflection api. 10 if (sSoleInstance != null){ 11 throw new RuntimeException("Use getInstance() method to get the single instance of this class."); 12 } 13 } 14 15 public static SingletonClass getInstance() { 16 //Double check locking pattern 17 if (sSoleInstance == null) { //Check for the first time 18 19 synchronized (SingletonClass.class) { //Check for the second time. 20 //if there is no instance available... create new one 21 if (sSoleInstance == null) { 22 sSoleInstance = new SingletonClass(); 23 } 24 } 25 } 26 27 ++refCounter; // 参照カウンターを加算 28 return sSoleInstance; 29 } 30 31 32 // 開放用のメソッド 33 public static synchronized release() { 34 if(sSoleInstance != null) { 35 --refCounter; 36 if(refCounter == 0) { 37 sSoleInstance = null; 38 } 39 } 40 } 41}
いま、スレッドAだけがSingletonClassのインスタンスを持っている状態(refCount=1
)で、新たにスレッドBがgetInstance()
を呼んだとします。それとほぼ同時にスレッドAがrelease()
を呼び出した場合、なにが起こるのでしょうか?release()
のsSoleInstance = null;
のあとにgetInstance()
のsSoleInstance = new SingletonClass();
が起こった場合は問題ないと思いますが、その逆はマズイのではないかと思います。どうすれば回避できるのでしょうか?

回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/04/28 11:06