Search code examples
javamultithreadingvolatilefinal

Why is volatile keyword not allowed for local variables?


Consider the snippet:

If in a main thread, I have this inside a method-

volatile CountDownLatch latch = new CountDownLatch(3);

new Thread(new ProcessThread("Worker1",latch, 20000)).start();//20 secs
new Thread(new ProcessThread("Worker2",latch, 60000)).start();//60 secs
new Thread(new ProcessThread("Worker3",latch, 40000)).start();//40 secs

I see that volatile is shown as an illegal modifier. And only final is permitted. And final guarantees initialization safety.

public static class ProcessThread implements Runnable {
  final CountDownLatch latch;
  final long workDuration;
  final String name;

  public ProcessThread(String name, CountDownLatch latch, long duration){
      this.name= name;
      this.latch = latch;
      this.workDuration = duration;
  }
}

The object below i.e new CountDownLatch(3) is properly constructed but I also want to make sure that the reference latch to which the above object is assigned is guaranteed to be visible to the code below it.

final CountDownLatch latch = new CountDownLatch(3);

Does the above code guarantee initialization so that latch is perfectly visible to the code below i.e

new Thread(new ProcessThread("Worker1",latch, 20000)).start();

Solution

  • And final guarantees initialization safety.

    Not on local variables: it just stops you reassigning that variable.

    final CountDownLatch latch = new CountDownLatch(3);
    

    Does the above code will guarantee initialization so that latch is perfectly visible to the code below i.e

    No. It's this code that guarantees it:

    public static class ProcessThread implements Runnable {
    
        final CountDownLatch latch;
    
        // Plus the assignment in the constructor.
    
    }
    

    final fields are guaranteed to be visible once the constructor completes (normally). From JLS Sec 17.5:

    An object is considered to be completely initialized when its constructor finishes. A thread that can only see a reference to an object after that object has been completely initialized is guaranteed to see the correctly initialized values for that object's final fields.