Why doesn't this code throw a NullPointerException?

Background

I would like to understand why the code snippet does not raise a NullPointerException.

Source

Consider the following code:

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(); } } 

The deliver method is called multiple times, while the following code runs in a separate thread:

  public void run() { agent.files = null; } 

There is only one instance of agent .

Problem

A NullPointerException is never thrown.

However, when the deliver method is paused, even for 0 milliseconds, a NullPointerException is thrown as expected:

  public void deliver() { if( files != null ) { Thread.currentThread().sleep( 0 ); if( files.iterator().hasNext() ) { File file = (File)files.iterator().next(); } } files = new ArrayList(); } 

I realized that theoretically there is a race condition between checking for files == null and calling files.iterator().hasNext() . In practice, I cannot start the race condition without entering a pause (i.e., Separating the zero check from the subsequent method call).

Question

Why doesn't the first deliver method throw an exception when null checking and usage are combined in the same expression?

+7
java nullpointerexception multithreading thread-safety
source share
1 answer

Two things:

  • Thread.sleep (0) still stops execution (possibly more than 0 milliseconds). In principle, even sleep mode 0 causes execution in this thread to stop briefly, and then restart. This gives another thread a chance to start and end, so you can trigger a race condition.

  • the files must be volatile , otherwise the JVM is allowed to optimize in such a way that you never notice that it changes value because it does not consider it necessary to maintain consistency between threads.

+5
source share

All Articles