JMM(Javaメモリモデル)は、ステートメントを自由に並べ替えることができます。
もちろん、これはマルチスレッド環境を扱うときに特に注意が必要です。
JMMの規則では、コンストラクターが終了する前、および参照がコンストラクター内から「エスケープ」されていない場合にのみ、変数は常に完全に初期化されますvolatile
。final
これは、「通常の」変数(非final
および非volatile
)が並行スレッドによって最新であると見なされることを期待されていないことを意味します。
私の質問は一見ばかげているように見えるかもしれませんが、実際にはそうではありません。
コンストラクターが完了した後にオブジェクトの参照セットが設定されていますか(完了は、既に作成されたすべての変数の初期化を意味するのではなく、単に「コンストラクター」プロセスの最後に到達することを意味します)?それを主張するJSRにルールはありますか?または、コンストラクターが完了する前に参照をクライアントに送り返すことができる例外的なケースが存在する可能性がありますか?
実際、ステートメントの並べ替えが非常に自由であると評判の場合は、オブジェクトの参照'happens-before'コンストラクターの送信が完了することを意味する場合もあります。ですから、this
避けるべき「脱出」の同じケースに出くわすでしょう。
一言で言えば、コンストラクターが完了した後に参照が常に送信されますか?
JLSを検索した後、オブジェクトの参照の戻りが関連する唯一の場所は次のとおりです:( JSR-12.5の抜粋)
結果として新しく作成されたオブジェクトへの参照が返される直前に、指定されたコンストラクターが処理され、次の手順を使用して新しいオブジェクトが初期化されます。
JMMとは関係ありません...したがって、コンストラクターの完了が常に発生することを保証できます-どのような場合でも参照を渡す前に。