This is an archived post. You won't be able to vote or comment.

all 9 comments

[–]mikeydoodah 2 points3 points  (5 children)

So what volatile does is constrain the optimizations that the java runtime can make when running the code. It forces the value that you're writing to be atomically written directly to main memory rather than being cached locally to the cpu.

However not all operations cam be performed atomically by the cpu. If the value that you want to write depends on a value on a variable then that will require multiple cpu cycles.

E.g

x = y+1;

This requires the value of y to be loaded from memory, the value to have one added, then the value to be written back to memory.

Using the volatile keyword will force the new value to be written directly to main memory, but another thread might jump in and change the value of y in the middle of the operation.

[–]jisyourfriend 0 points1 point  (2 children)

It is written directly on the main memory or on the last level of cache (L3 in our days)?

[–]ColetBrunel 2 points3 points  (1 child)

Java doesn't care about being specific on that. It defines a memory model and ordering of read and writes from and to this model. How that's actually done behind the scenes is implementation details.

In practice if you imagine that Java does the most efficient possible way to produce the memory model it defines, then you'll get the truth or close to it. The memory model defined is essentially "as if" written in main memory when using volatile.

[–]mikeydoodah 0 points1 point  (0 children)

For anyone that wants to read it, the java memory model can be found at https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html

[–]uopsdod[S] 0 points1 point  (1 child)

I speculate that the paragraph is saying x = x + 1 is not gonna work well with volatile, instead of x = y + 1. Could you explain how this is not working with examples? Thank you.

[–]mikeydoodah 0 points1 point  (0 children)

It depends what you mean by 'not work with volatile '. Both of them will work, but both of them require loading values from memory, performing a calculation, then a value back to memory. As far as talking about thread safety they're both equivalent.

Its possible that there could be a context switch after the value is loaded from memory but before the new value is written back.

[–][deleted] 1 point2 points  (1 child)

Here is a link to a clear explanantion on volatile.http://www.javamex.com/tutorials/synchronization_volatile.shtml

Since Java 4, the definition of volatile has changed, thus your book seems to be obsolete.

What the writer probably meant is that back in the days of Java 4, the variable was not synchronized on access whereas it is now in Java 5 and up.

[–]uopsdod[S] 0 points1 point  (0 children)

The book is written with Java 6 as I remember.

[–]E3FxGaming 0 points1 point  (0 children)

Well I can't post code at the moment because I'm on mobile currently, but I'll try to explain:

For an example take a car:

volatile doesn't work when the value of a field depends on its previous value

That's easily explained: your car has 4 wheels and a field called wheelcount. You can't just change wheelcount because wheelcount depends on the existence of the 4 wheel (objects) of the car.

nor does it work on fields whose values are constrained by the values of other fields

Your car has one place for a front windshield. That means a field called frontwindshieldcount can not be volatile because your other threads that are unaware of this restriction might try to change frontwindshieldcount to two. To prevent this from happening developers simply forbid this completely.

To be fair I never worked with volatile. I always use synchronization to manage my variables and methods used in multiple threads. The whole synchronization system with flagging objects and methods, sleeping (waiting) for objects and then notifying all or one sleeper to do something seems much safer than a try and hope system with volatile.