最初のオフ: はい、一般的に Java でシングルトンを行う最善の方法はenum
s を使用することですが、何らかの理由でシングルトン クラスをサブクラス化する必要がある場合は、列挙型を使用できないため...
JavaWorld の David Geary が、Java でのシングルトンの実装に関する記事をかなり前に公開しました。彼は、スレッドセーフなシングルトン実装に対する次の最適化には問題があると主張しました。
public static Singleton getInstance()
{
if (singleton == null)
{
synchronized(Singleton.class)
{
if(singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
Geary は、この「ダブルチェック ロック」の最適化について述べています。
シングルトンのコンストラクターが呼び出される前に、コンパイラーがシングルトン メンバー変数に値を自由に割り当てることができるため、動作が保証されません。その場合、スレッド 1 は、シングルトン参照が割り当てられた後、シングルトンが初期化される前に横取りされる可能性があるため、スレッド 2 は初期化されていないシングルトン インスタンスへの参照を返すことができます。
私の質問: 次の変更はその問題を解決するかどうか? 私は Goetz の Java 並行性の本を読み始めましたが、コンパイラーはスレッド内操作をシャッフルすることが許可されているようですsingleton = temp;
。そうすべき。説明してください。
public static Singleton getInstance()
{
if (singleton == null)
{
synchronized(Singleton.class)
{
if(singleton == null) {
Singleton temp = new Singleton();
singleton = temp;
}
}
}
return singleton;
}