Singleton

なんか mixiJava コミュニティで「Multi Thread って必要?」って話から Double Checked Locking の話になってそこから延々と Singleton の話に。
てかさ、Double Checked Locking がだめだって言っているのにこのコードはないべ。

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

これで問題ないとか言う人は Multi Thread Programming なんてしてはいかんとですよ。
でまぁ、なんか突っ込まれたら「Factory Object なら変更することは稀だから別に複数できても問題ない」って、それだったらそもそも Singleton にしなくてもいいんじゃね?それからずっとなんかグダグダ続いているみたいだけど。
Multi Thread を使うかどうかって話は「直接使うことはそんなに多くは無いけど、意識しないでプログラミングすることは少ない」って結論。まぁそだな。
で、そこで出てきていた Thread Safe な Singleton 実装の話とか。

素直に排他制御する

public class Singleton {
    private static Singleton instance;

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

まぁ、何のひねりもなし。呼び出しの度に排他制御のコストがかかるのがネック。いまどきならあまり気にする必要もないかも知れないが。

static initializer を使う

static field の初期化は一度だけなのが保証されているので、初期化時に代入してしまう。普通はこれでいい。

public class Singleton {
    private static Singleton instance = new Singleton();
    
    public static Singleton getInstance() {
        return instance;
    }
}

初期化が複雑になる場合は static initializer で。

public class Singleton {
    private static Singleton instance;

    static {
        instance = new Singleton();
    }
    
    public static Singleton getInstance() {
        return instance;
    }
}

内部クラスの static field でインスタンスを保持する

インスタンスの生成はできうる限り遅延させたい場合には内部クラスの static field でンスタンスを保持する

public class Singleton {
    private static class Holder {
        private static Singleton instance = new Singleton();
    }

    public static Singleton getInstance() {
        return Holder.instance;
    }
}

これならインスタンスの生成を Singleton クラスのロードよりさらに遅延させることができる。
ここまでする必要がどれくらいあるかといえば、あんまりないだろうなぁ。

そういや、synchronized ブロックって同期制御じゃなくて排他制御だよなぁ。案外混同している人多そう。