10

Marking a variable as volatile in Java ensures that every thread sees the value that was last written to it instead of some stale value. I was wondering how this is actually achieved. Does the JVM emit special instructions that flush the CPU cashes or something?

fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • Related question (the first in the list actually .. ) http://stackoverflow.com/questions/1787450/how-do-i-understand-read-memory-barriers-and-volatile – BalusC Apr 22 '10 at 21:02
  • And a thread I started on volatile with lots of "upvotes" and "favorites" regarding out-of-order execution: http://stackoverflow.com/questions/2441279/java-volatile-guarantees-and-out-of-order-execution – SyntaxT3rr0r Apr 22 '10 at 22:25

2 Answers2

10

From what I understand it always appears as if the cache has been flushed after write, and always appears as if reads are conducted straight from memory on read. The effect is that a Thread will always see the results of writes from another Thread and (according to the Java Memory Model) never a cached value. The actual implementation and CPU instructions will vary from one architecture to another however.

It doesn't guarantee correctness if you increment the variable in more than one thread, or check its value and take some action since obviously there is no actual synchronization. You can generally only guarantee correct execution if there is only just Thread writing to the variable and others are all reading.

Also note that a 64 bit NON-volatile variable can be read/written as two 32 bit variables, so the 32 bit variables are atomic on write but the 64 bit ones aren't. One half can be written before another - so the value read could be nether the old or the new value.

This is quite a helpful page from my bookmarks:

http://www.cs.umd.edu/~pugh/java/memoryModel/

gub
  • 5,079
  • 3
  • 28
  • 33
  • 2
    @jgubby: your last paragraph doesn't seem correct: you cannot read a 64-bit volatile that would have 32 bit from one write and the other 32 bit from another write. – SyntaxT3rr0r Apr 22 '10 at 22:28
  • 1
    @WizardOfOdds: Agreed. Meant to say NON-volatile variable there. – gub Apr 23 '10 at 14:49
  • @jbuggy: ah ah, that's what I thought but I didn't dare to edit your post because I wasn't sure what you meant :) Glad to help, because otherwise it was kinda confusing :))) – SyntaxT3rr0r Apr 23 '10 at 14:56
  • Seeing the writes of another thread is down to the *happens-before* relationship. Updates to`volatile`s are not necessarily immediate if that does not violate the *happens-before* rules. For instance, a compiler could merge two writes to a volatile if no other *happens-before* behaviour happens between. – Tom Hawtin - tackline Nov 02 '11 at 14:15
1

Exactly what happens is processor-specific. Generally there are some form of memory barrier instructions. Flushing the entire cache would obviously be very expensive - there are cache coherency protocols in the hardware.

Also important, is that certain optimisations are not made across the field accesses. The compiler is important when considering multithreading, don't just think about the hardware.

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305