What does "volatile" mean in Java?
Asked Answered
C

6

37

We use volatile in one of our projects to maintain the same copy of variable accessed by different threads. My question is whether it is alright to use volatile with static. The compiler does not give any errors but I don't understand the reason of using both.

Christianize answered 3/2, 2011 at 11:31 Comment(0)
G
29

Short of reading the memory model specification, I recommend you read http://jeremymanson.blogspot.com/2008/11/what-volatile-means-in-java.html. It's written by one of the Java Memory Model authors and should answer your question. Thinking of memory reads and writes in terms of the happens-before clause is also helpful; the JMM for Java 5 onwards adds happens-before semantics to volatile.

Specifically, when you read a volatile variable from one thread, all writes up to and including the write to that volatile variable from other threads are now visible to that one thread.

And, yes, you can use static with volatile. They do different things.

Grandmotherly answered 5/2, 2011 at 4:21 Comment(5)
Regarding your second paragraph: Do you mean all writes to all variables, or all writes to that one volatile variable?Carmoncarmona
I believe it's all writes to all variables prior to the last write to the volatile variable that's being read.Grandmotherly
"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." Bloch, Joshua; Goetz, Brian; Peierls, Tim; Bowbeer, Joseph; Holmes, David; Lea, Doug (2006-05-09). Java Concurrency in Practice (Kindle Locations 1194-1197). Pearson Education (US). Kindle Edition.Sawyer
The visibility effects of volatile variables extend beyond the value of the volatile variable itself. When thread A writes to a volatile variable and subsequently thread B reads that same variable, the values of all variables that were visible to A prior to writing to the volatile variable become visible to B after reading the volatile variable. Bloch, Joshua; Goetz, Brian; Peierls, Tim; Bowbeer, Joseph; Holmes, David; Lea, Doug (2006-05-09). Java Concurrency in Practice (Kindle Locations 1202-1205). Pearson Education (US). Kindle Edition.Sawyer
Lock-Free Thread Synchronization youtube.com/watch?v=KzDShvKbEMs#t=10mDrescher
M
13

volatile means that the variable changes at runtime and that the compiler should not cache its value for any reason.

This is only really a problem when sharing the variable amongst threads, you don't want a thread working with stale data, so the compiler should never cache the value of a volatile variable reference.

Maypole answered 5/2, 2011 at 4:34 Comment(0)
C
12

In Java, volatile has a similar general meaning as it does in C. The Java Memory Model (see the excellent link in ide's answer) allows threads to "see" a different value at the same time for variables marked as non-volatile. For example:

Thread a:

n = 1;
// wait...
n = 2;

Threads B and C:

while (true) {
    System.out.println(name + ": " + n);
}

This output is allowed to happen (note that you're not guaranteed to strictly alternate between B and C, I'm just trying to show the "changeover" of B and C here):

C: 1
B: 1
C: 2
B: 1
C: 2
B: 2

This is entirely separate from the lock taken by println; thread B is allowed to see n as 1 even after C finds out that it's 2. There are a variety of very good reasons for this that I can't pretend to fully understand, many pertaining to speed, and some pertaining to security.

If it's volatile, you're guaranteed (apart from the println's locking, which I'll ignore for the moment) that B and C will both "simultaneously" see the new value of B as soon as it is sent.

You can use volatile with static because they affect different things. volatile causes changes a variable to be "replicated" to all threads that use that variable before they use it, while static shares a single variable across all classes that use that variable. (This can be rather confusing to people new to threading in Java, because every Thread happens to be implemented as a class.)

China answered 5/2, 2011 at 4:38 Comment(0)
N
5

Consider a scenario when two thread (Thread1 and Thread2) are accessing same variable 'mObject' with value 1.

when a Thread1 runs, it doesn't expect other threads to modify the variable 'mObject'. In this scenario the Thread1 caches the variable 'mObject' with value 1.

And if the Thread2 modify the value of 'mObject' to 2, still the Thread1 would be refering the mObject value as 1 since it did caching. To avoid this caching we should to declare the variable as

private volatile int mObject;

in this scenarion the Thread1 will be getting updated value of mObject

Nib answered 9/8, 2017 at 18:58 Comment(0)
I
3

Small elaboration, but the volatile keyword isn't just for for memory visibility. Before Java ver 1.5 was released the volatile keyword declared that the field will get the most recent value of the object by hitting main memory each time for reads and flushing for writes.

In the latest Java versions, the volatile keyword says two very important things:

  1. Don't worry about how but know that when reading a volatile field you will always have the most up to date value.
  2. A compiler cannot reorder a volatile read/write as to maintain program order.

Check it out for more Java volatile examples.

Inhumane answered 5/8, 2019 at 20:35 Comment(1)
The only answer mentioning both caching and reordering. Plus the Java history.Liquidity
H
1

The Java volatile keyword is used to mark a Java variable as "being stored in main memory". More precisely that means, that every read of a volatile variable will be read from the computer's main memory, and not from the CPU cache, and that every write to a volatile variable will be written to main memory, and not just to the CPU cache. The value of an attribute is not cached thread-locally, and is always read from the "main memory".

Overcoming the data inconsistency problem is the advantage but reading from and writing to main memory is more expensive than accessing the CPU cache. Hence, if there are no specific requirements it is never recommended to use volatile keywords.

class Test  
{  
    static int var=5;  
} 

In the above example, assume that two threads are working on the same class. Both threads run on different processors where each thread has its local copy of var. If any thread modifies its value, the change will not reflect in the original one in the main memory. It leads to data inconsistency because the other thread is not aware of the modified value.

 class Test  
{  
   static volatile int var =5;  
}  

In the above example, the value of a volatile variable will never be stored in the cache. All read and write will be done from and to the main memory.

Humming answered 22/4, 2022 at 19:8 Comment(7)
This is a flawed mental model. shipilev.net/blog/2016/close-encounters-of-jmm-kind/…. CPU caches are always coherent, that is the responsibility of the cache coherence protocol. Main memory is just a spill bucket for whatever doesn't fit in the cache and can be completely stale.Zymase
Jeremy Manson one of the authors of the JMM says different, doesn't he?jeremymanson.blogspot.com/2008/11/… "For example, most processors nowadays have local caches. If one thread is reading from and writing to a cache on one processor, it may not see the same value as another thread writing and reading from another cache on another processor, depending on the processor's memory consistency model. One of the things that accessing a volatile variable effectively does on such machines is to say "reconcile the cache with main memory."Humming
To keep local caches in sync is the task of the cache coherence protocol. If one or more CPUs have read a cache line and the write of a different CPU needs to be committed to the cache, the cache line is first invalidated before the write can commit. I don't know any mainstream CPU lacking cache coherence. Thinking in terms of flushing to main memory is a flawed mental model and it will lead to making bad choices.Zymase
For example: if a local thread would continuously write to an uncontended volatile variable. With a flush-to-main-memory mental model, this is an extremely expensive operation because you will be consuming a lot of the memory bandwidth and I guess you want to stall the CPU as well. But if your mental model works based on cache coherence, the cache line will be owned by a single CPU and hence no cache coherence traffic and no traffic to main memory is needed. So continuously writing is relatively cheap.Zymase
In summary, the CPU / motherboard uses its cache coherence methods to make sure that all other CPUs caches can see the variables (volatile and non-volatile) in the other CPUs cache. But instruction reordering remains a challenge, which can affect visibility of non-volatile variables to other threads. Hence, the main reason for volatile keyword, after JSR-133, is preventing instruction reordering. Using volatile, you can ensure that non-volatile fields are visible to other threads by "happens-before" rules.Humming
Also, these variables are flushed from CPU registers to the CPU cache and not from CPU cache to main RAM. Is this correct? Thank you in advance.Humming
You are spot on. Reordering isn't the only thing volatile provides btw. There are 2 other concerns that need to be handled. (1) Atomicity: you don't want to end up with a torn read/write. (2) Visibility: the compiler should not optimize out a load/store. But AFAIK the biggest part of volatile is indeed controlling the order of memory actions.Zymase

© 2022 - 2024 — McMap. All rights reserved.