Java Volatile is Powerful
May 25, 2008
Post has been moved to our New Blog. http://blog.webscale.co.in/?p=19
Entry Filed under: Concurrency. Tags: Concurrency.
6 Comments Add your own
Leave a Comment
Some HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>
Trackback this post | Subscribe to the comments via RSS Feed
1.
pveentjer | May 27, 2008 at 4:19 am
You are forgettin one of the most powerful features of volatile: piggybacking on synchronization. It makes it possible to share objects with visibility problems in a threadsafe manner. Check the JMM topic in “Java Concurrency in Practice” for more info
2.
pavitar | May 27, 2008 at 6:51 am
Hi Peter,
I havent used term piggybacking explicitly but i have tried to explain the same concept. As when volatile write will happen it will execute a memory flush and all writes on other variables before volatile write will also get flushed. And due to ordering guarantees on volatile these other variable (non-volatile) writes wont jump over this volatile write. So thats nothing but piggybacking synchronization as explained by Brian in JCIP.
3.
Ben | May 28, 2008 at 11:14 am
The problem with volatile is that it wasn’t well defined until the JMM and, since so few developers seem to understand proper locking as is, I tend to avoid it. Instead I use the Atomic* implementations, even for a simple boolean flag, where a volatile would work just as well. An atomic is more obvious, better documented, and has nearly the same performance characteristics.
I think its good to inform people of the tricks, but best to advise them to use the library implementations instead. Otherwise, you’ll find more people implement counters using volatile and other such incorrect abuses because they only half understood your post.
4. roScripts - Webmaster resources and websites | May 28, 2008 at 11:15 pm
Java Volatile is Powerful « Pit Falls in Java Development…
Java Volatile is Powerful « Pit Falls in Java Development…
5.
Neil Coffey | September 3, 2008 at 8:22 am
Agree with the poster who said that volatile is poorly understood, though I think this is partly because the JMM per se is poorly understood (and that in turn because it is badly explained in the JLS).
In the tests above, it would also be interesting to measure overall throughput, and to look at how this changes with concurrency (number of accessing threads). Also, unless I missed it, you don’t mention what platform you’re running the tests on. The relative speed of processor instructions (and hence of the different locking mechanisms) almost certainly varies.
In case you’re interested, I’ve actually published some related test results looking e.g. at the performance of ConcurrentHashMap,
some timings of comparing locking mechanisms for concurrent array access,
plus some other information on volatile and synchronization that readers may find interesting.
6.
nonothing | February 13, 2009 at 8:40 pm
i’m not sure what you mean by “visibility” … and note, I AM NOT A GURU w/regards to synchronization … however, my understanding is that in synchronized(obj) { … } the current thread has exclusively acquired the “monior” for the “obj” within the {…} block. however, does that imply that all the java compiler will re-read the obj’s fields before using them within that block? will it commit changes to those fields before relinquishing the monitor at the end of the {…} block? apparently so. HOWEVER, what if there is a “wait” within the {…} block? IN THAT CASE the thread surrenders the monitor, and lets another thread have it, until some other thread calls “notify” on obj’s monitor. so, after “wait()”, what if the code now accesses one of obj’s fields? does the compiler re-read that field, if say it had prior been stored in an internal register? I DON’T KNOW. i recently saw some code on the internet for a comp sci class implementing a FIFO queue in which one thread reads, and another thread writes, which made use of wait / notify on the read/write sides, depending as buffer space was available on the write side, and whether data was available on the read side. in that code, volatile fields were used to keep track of the amount of data available, and the amount of writable buffer space available, which i took to mean that within a synchronized block, after a resuming from a “wait”, one can’t assume the compiler will re-read the obj’s field values if they’ve been changed by another thread. BUT I COULD BE WRONG, it could be after resumption from a “wait”, the compiler will refresh all registers that have been filled with obj’s field variables. until i learn otherwise, i’m assuming that values (in this case, object fields) which are altered via a wait/notify mechanism must be declared volatile. assuming this is true, it’s an oversipmlification to say that “synchrnoization” implies visibility, atomicitty, etc. what synchronization does is get exlusive use of a monitor. if you get that exclusive use, and then load VM registers with obj fields, etc., and OTHER threads only alter those fields after acquireing that monitor, then you can be sure that sematncis of visibility, atomicity, and ordering are maintained. i would assume if a VM register has been loaded with a field variable, your code calls “wait”, now you resume from the wait, and you access that field in later code, the compiler is not going to refresh those registers unless the field was marked volatile. i.e. once you resume from your wait, the coimpiler is going to contiue using that stale field data in the register. and that brings up the question, what if you load a local variable with an object field value before your synchroanized(obj) {…} block, and then in your synchornized block, access that field value directly, not the temporary variable. does the compiler reload the vm registers with the field variable? or does it use the value in the VM registers? i would assume the compiler continues to use the stale value. the only reason you’re often safe within synchronized(obj) { … } is that usually the first time you access a field value is within the { … } block, so the compiler is forced to fetch a fresh copy of the data into the registers. I COULD BE WRONG … but it’s frustrating i haven’t seen concurrency issues disucessed ont his level. if i do the following: int k = obj.myInt; synchronized(obj) { int j = obj.myInt; … } will the value of myInt be reloaded, or will the vale in the VM registers be used, to fill j?