簡體   English   中英

為什么這段代碼不會拋出NullPointerException?

[英]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方法在同一語句中組合空檢查和使用時不會拋出異常?

兩件事情:

  1. Thread.sleep(0)仍然停止執行(可能超過0毫秒)。 基本上,即使是0睡眠也會導致該線程上的執行暫時停止,然后重新啟動。 這使得另一個線程有機會運行和完成,這就是為什么你能夠觸發競爭條件。

  2. 文件應該是volatile ,否則允許JVM以這樣的方式進行優化,使得您可能永遠不會注意到它正在改變值,因為它不認為它需要保持線程之間的一致性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM