Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么这段代码不抛出NullPointerException? 背景_Java_Multithreading_Nullpointerexception_Thread Safety - Fatal编程技术网

Java 为什么这段代码不抛出NullPointerException? 背景

Java 为什么这段代码不抛出NullPointerException? 背景,java,multithreading,nullpointerexception,thread-safety,Java,Multithreading,Nullpointerexception,Thread Safety,我想理解为什么一段代码不抛出NullPointerException 源代码 考虑以下代码: public class Agent { public List files = new ArrayList(); public void deliver() { if( files != null && files.iterator().hasNext() ) { File file = (File)files.iterator().next();

我想理解为什么一段代码不抛出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;
  }
只有一个
代理
实例

问题 永远不会抛出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()
之间存在竞争条件。实际上,我不能在不引入暂停的情况下触发竞争条件(即,从随后的方法调用中分离空检查)

问题: 当空检查和用法组合在同一条语句中时,为什么第一个
交付方法不抛出异常?

两件事:

  • sleep(0)仍然停止执行(可能超过0毫秒)。基本上,即使是0睡眠也会导致该线程上的执行短暂停止,然后重新启动。这给了另一个线程运行和完成的机会,这就是为什么您能够触发竞速条件

  • 文件应该是易变的,否则JVM被允许以这样一种方式进行优化,您可能永远不会注意到它正在改变值,因为它认为它不需要保持线程之间的一致性


  • 您能否在适当的周围竞态条件区域发布
    javap
    输出?当您将
    文件设置为volatile
    时会发生什么?这是否意味着JVM可以将空检查和后续使用视为原子操作,除非显式设置为
    volatile
    ,否则线程可以具有变量的本地副本,如您的案例中的文件。因此,将文件设置为该线程之外的其他内容不会对局部变量产生影响。线程最终将检查外部修改,但在您的情况下,可能是在文件总是设置为值的情况下。Volatile将确保线程始终检查外部修改。所以:不,它不会将此视为一个原子操作,您只是幸运地在JVM中的机器上获得了示例。