5

What exactly is a situation where you would make use of the volatile keyword? And more importantly: How does the program benefit from doing so?

From what I've read and know already: volatile should be used for variables that are accessed by different threads, because they are slightly faster to read than non-volatile ones. If so, shouldn't there be a keyword to enforce the opposite?

Or are they actually synchronized between all threads? How are normal variables not?

I have a lot of multithreading code and I want to optimize it a bit. Of course I don't hope for huge performance enhancement (I don't have any problems with it atm anyway), but I'm always trying to make my code better. And I'm slightly confused with this keyword.

AyCe
  • 727
  • 2
  • 11
  • 30
  • Volatile is faster than synchronization because it doesn't require acquisition of a monitor lock. If you are already doing everything with synchronization then it probably doesn't matter. On the other hand, outside a synchronized block is the implementation defined Wild-Wild-West and there is no guarantee that any one thread sees what any other thread is doing. Volatile does a moderately sized list of things that the answers here have begun to touch on but I would recommend researching it for awhile if you really want a good grasp on it. – Radiodef Feb 22 '14 at 07:22
  • You really want to read [this](http://stackoverflow.com/a/10590927/144746) to get a full picture of how volatile works and what it actually does. Yes it's for C#, but the memory models between Java and the CLR are close to identical in that point. The interesting thing is that in neither the CLR nor the JMM spec does it ever say anything about "reading newest value from memory" - the ordering guarantees *almost* gives you this guarantee but there actually some edge cases. – Voo Feb 22 '14 at 15:22

5 Answers5

8

When a multithreaded program is running, and there is some shared variable which isn't declared as volatile, what these threads do is create a local copy of the variable, and work on the local copy instead. So the changes on the variable aren't reflected. This local copy is created because cached memory access is much faster compared to accessing variables from main memory.

When you declare a variable as volatile, it tells the program NOT to create any local copy of the variable and use the variable directly from the main memory.

By declaring a variable as volatile, we are telling the system that its value can change unexpectedly from anywhere, so always use the value which is kept in the main memory and always make changes to the value of the variable in the main memory and not create any local copies of the variable.

Note that volatile is not a substitute for synchronization, and when a field is declared volatile, the compiler and runtime are put on notice that this variable is shared and that operations on it should not be reordered with other memory operations. Volatile variables are not cached in registers or in caches where they are hidden from other processors, so a read of a volatile variable always returns the most recent write by any thread.

Aman Agnihotri
  • 2,973
  • 1
  • 18
  • 22
  • I've never used `volatile` and never had any problems with variables not being up-to-date, so I don't really know what you mean by `So the changes on the variable aren't reflected.`. So, `volatile` variables are in fact slower, but still faster for multiple threads? – AyCe Feb 22 '14 at 06:47
  • 1
    A volatile variable access is as fast as any non volatile variable access. But its access is slower compared to the access of cached variables, which the JVM creates in order to execute Java programs fast. The volatile variable remains in the main memory and so its like a one-place lookup of the variable for any thread which wants to use it. If any variable isn't volatile and multiple threads are using it, then they are free to create cached/local copies of the variable and so now that variable is in multiple places in the memory, and that's not what the programmer might want. – Aman Agnihotri Feb 22 '14 at 06:51
2

Volatile make accessing the variables slower by having every thread actually access the value each time from memory thus getting the newest value.

This is useful when accessing the variable from different threads.

Use a profiler to tune code and read Tips optimizing Java code

Javier
  • 2,752
  • 15
  • 30
  • Okay, but what if I use `synchronized` every time I change multithreaded variables anyway (that's what I do mostly)? Would they benefit from being `volatile`? Or is this intended for variables that are not explicitly locked? – AyCe Feb 22 '14 at 06:52
  • Synchronized is volatile+locking. It's very unusual to use volatile. – Javier Feb 22 '14 at 06:55
  • The link @lalaland posted (https://stackoverflow.com/questions/106591/do-you-ever-use-the-volatile-keyword-in-java) is good although a bit technical. – Javier Feb 22 '14 at 06:58
  • 1
    If you're using synchronization (properly) you probably don't need volatile. When you synchronize on an object, any changes made to shared memory inside that block are seen by other threads as soon as they synchronize on that same object. Volatile is a way to guarantee visibility of shared memory without synchronization. – Radiodef Feb 22 '14 at 07:00
2

The volatile keyword means that the compiler will force a new read of the variable every time it is referenced. This is useful when that variable is something other than standard memory. Take for instance an embedded system where you're reading a hardware register or interface which appears as a memory location to the processor. External system changes which change the value of that register will not be read correctly if the processor is using a cached value that was read earlier. Using volatile forces a new read and keeps everything synchronized.

Chris Ryding
  • 1,508
  • 11
  • 16
  • Nice, but it seems that everything already IS synchronized. From all the answers I've got, it seems to me that `volatile` doesn't really do anything that the VM wouldn't do by itself anyway. But will it improve speed for accessing the variables, for example? – AyCe Feb 22 '14 at 06:58
1

Heres a good stack overflow explanation

and Heres a good wiki article

In computer programming, particularly in the C, C++, C#, and Java programming languages, a variable or object declared with the volatile keyword usually has special properties related to optimization and/or threading. Generally speaking, the volatile keyword is intended to prevent the compiler from applying certain optimizations which it might have otherwise applied because ordinarily it is assumed variables cannot change value "on their own."

**^wiki

In short it guarantees that a given thread access the same copy of some data. Any changes in one thread would immediately be noticeable within another thread

Community
  • 1
  • 1
t3dodson
  • 3,949
  • 2
  • 29
  • 40
  • So `volatile` is just a "hint", right? Something that one can consider to use when the current code is too slow? I'm still unsure which variables I should declare `volatile`. What do you mean with `this is usually BAD!`? – AyCe Feb 22 '14 at 06:42
  • @AyCe No, volatile is not just a hint. There are rules specifically associated with it. Without volatile, you can make a write to a variable on one thread and other threads are theoretically allowed to **never** see that write. In reality, other threads will eventually see that write but the delay can be long enough as to be even perceptible by a human. Volatile means other threads will see that write immediately (among other things that it does). – Radiodef Feb 22 '14 at 06:50
  • @Radiodef I've been doing multithreading stuff for years now and could never observe such behaviour. :O I wonder if the VM is just very nice to people doing it wrong or I actually did everything right with synchronized? – AyCe Feb 22 '14 at 11:29
  • Probably both. Assuming you've been using synchronization correctly then things probably worked because of that. The reality is also that threads do typically see non-volatile non-synchronized writes eventually so the error only looks like a very slight delay. Volatile also does something that synchronization does not which is that it prevents a compiler from refactoring statements involving the variable. This can prevent very subtle bugs like the infamous [double-checked locking inlined constructor](http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html). – Radiodef Feb 22 '14 at 21:13
  • @Radiodef I've just read this. Currently I'm using a singleton pattern for some classes that only need 1 instance by having a static instance and get-function that stores a newly-created object in the instance field if it's null. From what I've read there it seems that by using static the processor will always access the same memory and I should not have this problem. It's not synchronized, but I can guarantee, based on the order of my code, that 2 threads will never access the get-function at the same time when it hasn't been accessed before. – AyCe Feb 25 '14 at 03:21
  • It sounds like what you're doing is probably safe. (See [actions that cause a happens-before](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility). Namely I am thinking here, starting a thread.) Though for the record, the preferred way to do lazy instantiation in Java is the [initialization on demand holder idiom](https://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom). – Radiodef Feb 25 '14 at 04:03
1

volatile concerns memory visibility. The value of the volatile variable becomes visible to all readers after a write operation completes on it. Kind of like turning off caching.

Here is a good stack overflow response: Do you ever use the volatile keyword in Java?

Concerning specific questions, no they are not synchronized. You still need to use locking to accomplish that. Normal variables are neither synchronized or volatile.

To optimize threaded code its probably worth reading up on granularity, optimistic and pessimistic locking.

Community
  • 1
  • 1
lalaland
  • 71
  • 3
  • It seems to me that `volatile` only promises to do what is (seemingly?) already done by the VM. The example from the first answer in your linked thread is something I would do with `synchronized` - seems cleaner to me. – AyCe Feb 22 '14 at 06:56
  • Double checked locking is an example of where you need both `synchronized` and `volatile`, seeing them being applied here may help: http://en.wikipedia.org/wiki/Double-checked_locking – lalaland Feb 22 '14 at 07:26
  • I've just read some of that Wikipedia article. So far it seems as if I don't need the described pattern for my intents - all lazy initialization is done thread-safe anyway. But reading `Since synchronizing a method can decrease performance by a factor of 100 or higher` made me think about my current code, I had not assumed the impact would be SO dramatic. I use `synchronized` almost everywhere where it makes sense, but I did not expect it to be THAT expensive! – AyCe Feb 22 '14 at 11:38