背景
我想明白爲什麼一個代碼片段確實不拋出NullPointerException。爲什麼此代碼不會拋出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
實例。
問題
從不拋出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()
。在實踐中,我不能引入競爭條件而不引入暫停(即將後續方法調用中的空檢查拆分)。
問題
爲什麼第一deliver
方法當空校驗和使用在同一語句組合不會拋出異常?
你可以發佈'javap'輸出在適當的周圍比賽條件區域嗎? – hexafraction
當你製作'files'' volatile'時會發生什麼? – OldCurmudgeon