「ダブル・チェック・ロッキング」の版間の差分
imported>Administrator 編集の要約なし |
|||
| 77行目: | 77行目: | ||
=== 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では「new(メモリ確保)」と「コンストラクタ実行」のタイミングが異なる。 | ||
[[Java]]では絶対にダブルチェックロッキングを使用してはならない。 | よって、[[Java]]では絶対にダブルチェックロッキングを使用してはならない。 | ||
たとえば以下のような[[Java]]の[[ソースコード]]があったとする。 | たとえば以下のような[[Java]]の[[ソースコード]]があったとする。 | ||
| 89行目: | 89行目: | ||
# 1行目で[[メモリ]]が確保される。 | # 1行目で[[メモリ]]が確保される。 | ||
#: いわゆるmallocが実行されhage[[変数]]自体は[[null]]ではなくなる。 | #: いわゆるmallocが実行されhage[[変数]]自体は[[null]]ではなくなる。 | ||
#: ただし[[コンストラクタ]] | #: ただし[[コンストラクタ]]はまだ実行されていない。 | ||
# | # 2行目のインスタンスを初めて使うときにコンストラクタが実行される。 | ||
#: [[コンストラクタ]]が実行されるタイミングは、オリジナル(newを実行した[[スレッド]]の持つ)インスタンスに対して外部から[[メンバー関数]]や[[メンバー変数]]に初回アクセスがあったときとなる。これを[[遅延初期化]](lazy initialization)という。これによりhage[[変数]]自体は[[null]]ではないので後続スレッドはコンストラクタを実行していない不完全な[[インスタンス]]の[[参照]]を取得できてしまう。 | #: [[コンストラクタ]]が実行されるタイミングは、オリジナル(newを実行した[[スレッド]]の持つ)インスタンスに対して外部から[[メンバー関数]]や[[メンバー変数]]に初回アクセスがあったときとなる。これを[[遅延初期化]](lazy initialization)という。これによりhage[[変数]]自体は[[null]]ではないので後続スレッドはコンストラクタを実行していない不完全な[[インスタンス]]の[[参照]]を取得できてしまう。 | ||