バックグラウンド
コードのスニペットがNullPointerException をスローしない理由を理解したいと思います。
ソースコード
次のコードを検討してください。
public class Agent {
public List files = new ArrayList();
public void deliver() {
if( files != null && files.iterator().hasNext() ) {
File file = (File)files.iterator().next();
}
files = new ArrayList();
}
}
deliver
メソッドは繰り返し呼び出されますが、次のコードは別のスレッドで実行されます。
public void run() {
agent.files = null;
}
agent
インスタンスは 1 つだけです。
問題
NullPointerException がスローされることはありません。
ただし、deliver
メソッドが一時停止すると、0 ミリ秒であっても、予想どおり NullPointerException がスローされます。
public void deliver() {
if( files != null ) {
Thread.currentThread().sleep( 0 );
if( files.iterator().hasNext() ) {
File file = (File)files.iterator().next();
}
}
files = new ArrayList();
}
私の理解では、理論的には、のチェックfiles == null
と呼び出しの間に競合状態があるということfiles.iterator().hasNext()
でした。実際には、一時停止を導入せずに競合状態をトリガーすることはできません (つまり、後続のメソッド呼び出しから null チェックを分割します)。
質問
deliver
null チェックと使用法が同じステートメントで組み合わされている場合、最初のメソッドが例外をスローしないのはなぜですか?