[英]Why does this code not throw a 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
方法在同一語句中組合空檢查和使用時不會拋出異常?
兩件事情:
Thread.sleep(0)仍然停止執行(可能超過0毫秒)。 基本上,即使是0睡眠也會導致該線程上的執行暫時停止,然后重新啟動。 這使得另一個線程有機會運行和完成,這就是為什么你能夠觸發競爭條件。
文件應該是volatile
,否則允許JVM以這樣的方式進行優化,使得您可能永遠不會注意到它正在改變值,因為它不認為它需要保持線程之間的一致性。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.