「ダブル・チェック・ロッキング」の版間の差分

imported>Piyo
imported>GamerBook
76行目: 76行目:


=== Java ===
=== Java ===
[[Java]]では仕様において[[アウトオブオーダー]]を用いるメモリモデルが可能となっていたため、この[[イディオム]]を使うことには問題があり、一部の実装では実際に正しく働かない可能性があることが知られている。 http://www.ibm.com/developerworks/jp/java/library/j-dcl/ を参照。
[[Java]]では仕様において[[アウトオブオーダー]]を用いるメモリモデルが可能となっていたため、この[[イディオム]]を使うことには問題があり、一部の実装では実際に正しく働かない可能性があることが知られている。詳細は http://www.ibm.com/developerworks/jp/java/library/j-dcl/ を参照。
 
 
たとえば以下のような[[Java]]の[[ソースコード]]があったとする。
<source lang="java">
Person hage = new Person();
</source>
これが一部のJava実装では以下のような動作になる。
# [[メモリ]]上に[[インスタンス]]が確保さる。
#: hage[[変数]]自体は[[null]]ではなくなる。
# [[コンストラクタ]]は実行されない。
#: [[コンストラクタ]]が実行されるタイミングは、オリジナル(newを実行した[[スレッド]]の持つ)インスタンスに対して外部から[[メンバー関数]]や[[メンバー変数]]に初回アクセスがあったとき。これを[[遅延初期化]](lazy initialization)という。これによりhage[[変数]]自体は[[null]]ではないので後続スレッドはコンストラクタを実行していない不完全な[[インスタンス]]の[[参照]]を取得できてしまう。
 
<source lang="java">
public static Singleton getInstance()
{
    // 1: 先行スレッドから見た場合はnull
    //
    // 3: 後続スレッドから見た場合は非null、
    //    ただしコンストラクタが実行されていない不完全なものである場合がある。
    if (instance == null)
    {
        synchronized(Singleton.class)
        {
            if (instance == null)
            {
                // 2:
                // 先行スレッドによりメモリが割り当てられてnullではなくなるが、
                // この時点でコンストラクタは実行されていない。
                instance = new Singleton();
            }
        }
    }
    return instance;
}
</source>


== 関連項目 ==
== 関連項目 ==