'Why can an Object member variable not be both final and volatile in Java?
If in a class I have a ConcurrentHashMap instance that will be modified and read by multiple threads I might define like this:
public class My Class {
private volatile ConcurrentHashMap<String,String> myMap = new ConcurrentHashMap<String,String>();
...
}
adding final
to the myMap field results in an error saying I can only use final or volatile. Why can it not be both?
Solution 1:[1]
volatile
only has relevance to modifications of the variable itself, not the object it refers to. It makes no sense to have a final volatile
field because final fields cannot be modified. Just declare the field final
and it should be fine.
Solution 2:[2]
It's because of Java Memory Model (JMM).
Essentially, when you declare object field as final
you need to initialize it in object's constructor and then final
field won't change it's value. And JMM promises that after ctor is finished any thread will see the same (correct) value of final
field. So, you won't need to use explicit synchronization, such as synchronize
or Lock
to allow all threads to see correct value of final
field.
When you declare object's field as volatile
, field's value can change, but still every read of value from any thread will see latest value written to it.
So, final
and volatile
achieve same purpose -- visibility of object's field value, but first is specifically used for a variable may only be assigned to once and second is used for a variable that can be changed many times.
References:
Solution 3:[3]
Because volatile
and final
are two extreme ends in Java
volatile
means the variable is bound to changes
final
means the value of the variable will never change whatsoever
Solution 4:[4]
volatile
is used for variables that their value may change, in certain cases, otherwise there is no need for volatile
, and final
means that the variable may not change, so there's no need for volatile
.
Your concurrency concerns are important, but making the HashMap
volatile will not solve the problem, for handling the concurrency issues, you already use ConcurrentHashMap
.
Solution 5:[5]
A volatile
field gives you guarantees as what happens when you change it. (No an object which it might be a reference to)
A final
field cannot be changed (What the fields reference can be changed)
It makes no sense to have both.
Solution 6:[6]
volatile
modifier guarantees that all reads and writes go straight to main memory, i.e. like the variable access is almost into synchronized
block. This is irrelevant for final variable that cannot be changed.
Solution 7:[7]
Because it doesn't make any sense. Volatile affects object reference value, not the object's fields/etc.
In your situation (you have concurrent map) you should do the field final
.
Solution 8:[8]
In a multithread environment different threads will read a variable from main memory and add it to the CPU cache. It may result in two different threads making changes on the same variable, while ignoring each others results. enter image description here
We use word volatile to indicate that variable will be saved in main memory and will be read from main memory. Thus whenever a thread want to read/write a variable it will be done from main memory, essentially making a variable safe in multithread environment.
When we use final keyword we indicate that variable will not change. As you can see if a variable is unchangeable, than it doesn't matter if multiple threads will use it. No thread can change the variable, so even if variable is saved to CPU caches at different times, and threads will use this variable at different times than it's still ok, because the variable can only be read.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Michael Borgwardt |
Solution 2 | nish1013 |
Solution 3 | Sunil Kumar B M |
Solution 4 | MByD |
Solution 5 | Evgeniy Dorofeev |
Solution 6 | Vishal Yadav |
Solution 7 | kan |
Solution 8 | M1kyyy |