Java volatil

In my professional career I’ve came across some issues around Java volatil variables, it comes very handy when multi-core computers arrived. The semantic in Java has changed in it’s 5th version, and it still is a bad documented, badly known and used concept. So it’s time to stop, think, read, learn and mature the concepts. So, what it is? Why do we need it? And most important, should we try to use it?

What is it?

Just to mention that volatil keyword is not only used in Java. C, C++ and C# for example, also support this keyword, however, the semantic is different across all of them, still all relates to compilation optimisations or concurrency.

In Java when you mark a variable as volatil that means you are telling the JVM to take special care when dealing with them. Basically they provide a weaker synchronisation method.

How does JVM handles it?

When dealing with volatil variables JVM will not, for example, cache it’s value in a thread local context. Basically, all read and writes will affect directly, no matter what, the main memory. The JVM will also manage accesses to this variable as it was surrounded by a synchronized block on it-self (mutually exclusive code). It also signals the JVM to not try any kind of re-ordering optimisation when using such variables.

 

Why do we need it?

From what I said earlier there are some scenarios where volatil variables could be used. Let’s see an example.

If you have 2 CPU trying to modify the same variable, each CPU has it’s own local cache, then the same variable could then have different values. If the variables are declared as volatil is secure that it’s the value in the main memory that will be modified.

However, volatil is not the only way to achieve this behaviour (as you might already know). So, it’s important to understand that, in Java concurrency there are two different important concepts:

  • Execution control (mainly to avoid race conditions)
  • Memory visibility (state of the memory seen by threads)

Synchronisation blocks allow you to accomplish the same but in bigger blocks. For example, after thread A releases a lock and before another thread B acquiring the same lock, the local memory of the thread A gets copied to the main memory and also thread B will have its local cached view of the main memory updated (this is named the ‘happens-before’ memory barrier).

So basically volatil variables allow the same behaviour but only related with that specific variable. Since Java 5, writing to a volatile field has the same memory effect as a monitor release, and reading from a volatile field has the same memory effect as a monitor acquire. Now, usages of volatil variables cannot be re-ordered by the compiler/JVM neither switching with non-volatil variables (that was the improvement in the new memory model).

Should we use it?

Well, although the performance of both synchronised/volatil are pretty much the same, there are some scenarios where you may say that you don’t need the entire synchronised block to make it work. For example, if you want to multiple threads to just be synchronised around one single variable, then using it as volatil would be really clever.

However, from my point of view, using volatil is really hard to maintain. In terms of code readability it’s hard to identify variables as volatil because it’s only specified during the variable declaration. I will find easier to read code without volatil and also easier to maintain. From my experience, code readability and maintenance is key in multithreading development.

Tags: ,

July 12, 2014 Concurrency, Java