1

I have a reader and writer thread in java and below is the code snippet.

int volatile ready = false;
int var1;
int var2;
int var3;

T1:
while(!ready);
  print var1;
  print var2;
  print var3;


T2:
var1 = 1;
var2 = 2;
var3 = 3;
ready = true;

Is it possible that var1, var2 and var3 are allocated in a register in T2. In C++, this is prevented by marking var1, var2 and var3 as volatile. But in Java, do these variable need to be marked as volatile too?

KodeWarrior
  • 3,538
  • 3
  • 26
  • 40
  • `volatile` is not a thread synchronization mechanism in C++; even with `volatile` on all variables, this pattern would be unsafe in C++. – user2357112 Sep 05 '17 at 18:27
  • 1
    Also, your T1 *stops* printing the variables when the `ready` flag is set, rather than waiting for T2 to set the flag before printing. – user2357112 Sep 05 '17 at 18:28
  • edited the question – KodeWarrior Sep 05 '17 at 18:31
  • Yes, you need them to be volatile or use another mechanism (such as using `synchronized`) if you want to be sure that `T1` sees the changed made in `T2`. – Kayaman Sep 05 '17 at 18:32
  • 2
    Note: `System.out.println` uses a `synchronized` block making the `volatile` redundant. – Peter Lawrey Sep 05 '17 at 18:33
  • 1
    Your control over what is allocated to a register is even less than in C++ and if you're familiar with C++ `volatile` it's useful to think of Java `volatile` as entirely unrelated. – pvg Sep 05 '17 at 18:37
  • I do know volatile in C++ and Java is different. I don't agree with there is no control in C++. To prevent register allocation u just mark it volatile. However, it does not guarantee happens before relationship. – KodeWarrior Sep 05 '17 at 18:40
  • @PeterLawrey Thanks! Did not know about this. – KodeWarrior Sep 05 '17 at 18:55
  • @KodeWarrior That's not accurate. The C++ standard doesn't connect `volatile` to registers at all. It does suggest certain semantics. – pvg Sep 05 '17 at 19:32
  • With volatile, the compiler does not touch that variable. As a result, register allocation is prevented. – KodeWarrior Sep 05 '17 at 20:20
  • "the compiler does not touch that variable" is hardly a meaningful thing to say. You're really better off thinking about the semantics the languages defined than simplified just-so stories about how this works - it's useful as a first pass but leads to the kind of misunderstandings you're encountering – pvg Sep 05 '17 at 20:37
  • I agree with you. In fact, in the answer I have accepted I had mentioned about this. I come from the land of C++98 which did not have a memory model. – KodeWarrior Sep 05 '17 at 21:28

1 Answers1

1

But in Java, do these variable need to be marked as volatile too?

If you only care about whether their values will become visible to T1, no, they don't need to be volatile.

Due to ready being volatile, JSR 133 guarantees a happens-before relationship between T2's writes and T1's reads.

See the detailed explanation in the FAQ: https://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#volatile

NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • I read through the documentation and understood that there is a happens before a relationship. Does this mean that there are no register allocations for all the nonvolatile variables before a volatile write or can there be register allocation but the values are moved to the memory location of the variable and finally flushed as a result of the fence introduced by a volatile write? – KodeWarrior Sep 05 '17 at 18:44
  • @KodeWarrior: I've never seen a Java runtime or JIT complier make guarantees to its users about where it places variables. The guarantees tend to be about observable semantics. If you really care about what your runtime does, look at the disassembly (https://stackoverflow.com/questions/1503479/how-to-see-jit-compiled-code-in-jvm). – NPE Sep 05 '17 at 18:50
  • Okay, thinking in terms of visibility makes sense. Thanks, NPE. – KodeWarrior Sep 05 '17 at 18:51