为什么此代码不会抛出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以这样的方式进行优化,以至于您可能永远不会注意到它正在改变价值,因为它不认为需要维护线程之间的一致性。

  • 链接地址: http://www.djcxy.com/p/13267.html

    上一篇: Why does this code not throw a NullPointerException?

    下一篇: Why can I throw null in Java?