コードを考える:
new Thread(new BackgroundWorker()).start();
直感的には、BackgroundWorkerインスタンスはスレッドが終了するまでGCから安全であるように見えますが、これは事実ですか?なぜ ?
編集:
この熱はすべて、基本的に同じ投稿で少なくとも2つの異なる質問をすることによって生成されます。タイトルの質問には1つの答えがあります。コードサンプルは異なる方向に進みます-インライン化に応じて2つの可能な結果があります。
投稿された回答は本当に素晴らしいです。Software Monkeyに緑色のチェックボックスを授与します。Darronの回答も同様に有効ですが、Software Monkeyが私が抱えていた問題を説明していることに注意してください。それは私のために働いた答えでした。
これを思い出深いものにしてくれてありがとう;)
はい、GCはどのスレッドからも到達できないオブジェクトのみを収集でき、Threadはその実行可能オブジェクトへの参照を保持する必要があるため(またはそれを呼び出すことができないため)。つまり、スレッドの実行中にRunnableオブジェクトに到達できることは明らかです。
実行に必要なセマンティクスに関係なく、この新しいスレッドまたは他のスレッドが到達できなくなるまで、オブジェクトはGCされません。これは、少なくともRunnableのrun()を呼び出すのに十分な長さであり、そのスレッドがRunnableインスタンスに到達できる場合は、スレッドの存続期間全体にわたって、JVM仕様によって構成が安全であることが保証されます。
編集:ダロンはこれを打ち負かしており、一部は彼の議論に確信しているように見えるので、私は彼の説明に基づいて、私の説明をさらに詳しく説明します。
今のところ、Thread以外の人がThread.run()を呼び出すことが合法ではないと仮定します。
その場合、Thread.run()のデフォルト実装は次のようになります。
void run() {
Runnable tmp = this.myRunnable; // Assume JIT make this a register variable.
this.myRunnable = null; // Release for GC.
if(tmp != null) {
tmp.run(); // If the code inside tmp.run() overwrites the register, GC can occur.
}
}
この場合、tmpは依然としてThread.run()内で実行されているスレッドが到達可能なランナブルへの参照であるため、GCの対象にはなりません。
(不可解な理由により)コードが次のようになった場合:
void run() {
Runnable tmp = this.myRunnable; // Assume JIT make this a register variable.
this.myRunnable = null; // Release for GC.
if(tmp != null) {
tmp.run(); // If the code inside tmp.run() overwrites the register, GC can occur.
System.out.println("Executed runnable: "+tmp.hashCode());
}
}
明らかに、tmp.run()の実行中に、tmpによって参照されるインスタンスをGCすることはできません。
Darronは、到達可能とは、実行中のスレッドから見える参照として定義されているのではなく、すべてのThreadインスタンスから始まるインスタンス参照をルートとして追跡することによって見つかる参照のみを意味すると誤って信じていると思います。どちらか、または私は反対を信じていると誤解されています。
さらに、DarronはJITコンパイラーが好きな変更を行うと想定できます。コンパイラーは実行中のコードの参照セマンティクスを変更することはできません。到達可能な参照を持つコードを記述した場合、コンパイラーはその参照を最適化できず、その参照がスコープ内にある間にオブジェクトが収集されます。
到達可能なオブジェクトが実際にどのように見つかるかの詳細はわかりません。私は私が保持しなければならないと思う論理を推定しているだけです。私の推論が正しくなかった場合、メソッド内でインスタンス化され、そのメソッドのローカル変数にのみ割り当てられたオブジェクトは、すぐにGCに適格になります。
さらに、全体の議論は議論の余地があります。到達可能な唯一の参照がThread.run()メソッドにある場合、ランナブルのrunはそのインスタンスを参照せず、インスタンスへの他の参照が存在しないため、run()メソッドに暗黙的にthisが渡されます(バイトコードではなく、宣言された引数として)、オブジェクトインスタンスが収集されるかどうかは問題ではありません。暗黙的にこれが最適化されている場合、コードを実行する必要がないため、定義により、害を及ぼすことはありません。その場合、Darronが正しい場合でも、最終的な実際の結果は、OPによって想定される構成が完全に安全であるということです。どちらにしても。それは問題ではありません。はっきりさせておきますが、もう一度繰り返します。最後の分析ではそれは問題ではありません。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加