8

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();
GhostCat
  • 137,827
  • 25
  • 176
  • 248
Farhan stands with Palestine
  • 13,890
  • 13
  • 58
  • 105
  • It's a bit unclear what you're asking. When you say at the end "perfectly visible to the code below i.e." do you mean the line of code you quote, the call to the constructors? (I realize that may be obvious.) Or the code *within* the constructors? – T.J. Crowder Oct 10 '16 at 07:21
  • 1
    @T.J.Crowder surely the code within the constructor is executed in the same thread as the call to the constructor...? It's the `run()` method which is (potentially) run in a different thread. – Andy Turner Oct 10 '16 at 07:39
  • @AndyTurner: Of course it does, I wasn't suggesting otherwise. I was suggesting the OP clarify what he's asking, particularly given the use of `volatile` on a local. – T.J. Crowder Oct 10 '16 at 07:46

3 Answers3

13

Local variables live on the stack; and of course, when you invoke the same method twice, they have all their local variables on their individual stacks.

volatile only makes sense when multiple threads would be writing to the same memory location (on the heap).

Which makes absolutely no sense for local variables from within the body of a method!

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • 1
    I think the OP's main concern is expressed at the very end, wrt initialization of the local prior to passing it into a constructor. Probably worth addressing that directly. – T.J. Crowder Oct 10 '16 at 07:16
  • 2
    I guess Andy beat me there; but you are right; I kinda overlooked that aspect. – GhostCat Oct 10 '16 at 07:52
  • Not correct. For example, what if you have the callbacks of futures closing over local variables within a method? – ig-dev Nov 30 '19 at 00:40
2

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.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • That means when latch is passed to the the constructor `new ProcessThread("Worker1",latch, 20000))`, it can be null also. – Farhan stands with Palestine Oct 10 '16 at 07:22
  • When you OP says at the end "perfectly visible to the code below i.e." they quote a *call* to the constructor, not the constructor. They're different `latch`s. – T.J. Crowder Oct 10 '16 at 07:22
  • @ShirgillFarhanAnsari sure it can be `null`, if that's what you pass. – Andy Turner Oct 10 '16 at 07:23
  • No, I am not passing null but I am unsure whether the assignment made to latch in i.e `final CountDownLatch latch = new CountDownLatch(3);` is visible when this is c/d `new ProcessThread("Worker1",latch, 20000))` – Farhan stands with Palestine Oct 10 '16 at 07:27
  • 1
    The value of `latch` is visible when you call `new ProcessThread("Worker1",latch, 20000))` because it's executed in the same thread. – Andy Turner Oct 10 '16 at 07:27
  • Thanks. I will mark your answer as correct. But is your last comment documented somewhere in JLS. – Farhan stands with Palestine Oct 10 '16 at 07:29
  • 1
    @ShirgillFarhanAnsari No it cannot be null, since you have just initialized it in the line above with `CountDownLatch latch = new CountDownLatch(3);` Remember that `new ProcessThread` just executes on the same thread. New threads aren't started until you call the `start` method, and the call to `Thread.start` synchronized-with the first instruction on the thread (JLS 17.4.4), so you don't need to worry about data visibility issues in this particular case. – Erwin Bolwidt Oct 10 '16 at 07:30
  • @ErwinBolwidt: So final keyword has nothing to do with the visibility in this case. It just here prevents reassignment. – Farhan stands with Palestine Oct 10 '16 at 07:32
  • @ShirgillFarhanAnsari Correct – Erwin Bolwidt Oct 10 '16 at 07:34
  • @ErwinBolwidt: Okay, the visibility is guaranteed in the particular case above. But it begs another questions. What about the case when I do `final CountDownLatch latch = new CountDownLatch(3);` and then afterwards there is a `callSomeMethod(latch)` . I surmise that `latch` could be `null` when the method `callSomeMethod(latch)` is called. – Farhan stands with Palestine Oct 10 '16 at 07:57
  • @ShirgillFarhanAnsari As long as it is on the same thread - and it looks like that is what you mean - then there is never a visibility issue. – Erwin Bolwidt Oct 10 '16 at 08:38
  • @ErwinBolwidt: Thanks indeed. – Farhan stands with Palestine Oct 10 '16 at 08:40
  • @ErwinBolwidt: oh I recall this thread, http://stackoverflow.com/questions/38694206/will-an-instruction-statement-which-comes-before-other-s-guaranteed-to-be-execut where it is written that its not guaranteed in general if statement 1 comes before statement 2 within the current thread. Just wish to have your opinion. – Farhan stands with Palestine Oct 10 '16 at 08:46
0

Operations you perform locally will not have visibility or interference issues by other threads so it does not make sense to declare local variable volatile.

javaq
  • 131
  • 1
  • 9