If I have an object which is shared between threads, it seems to me that every field should be either final
or volatile
, with the following reasoning:
if the field should be changed (point to another object, update the primitive value), then the field should be
volatile
so that all other threads operate on the new value. Merely a synchronization on the methods which access said field is insufficient because they might return a cached value.if the field should never change, make it
final
.
However, I could not find anything about this, so I wonder whether this logic is flawed or just too obvious?
EDIT of course instead of volatile one might use a final AtomicReference
or similar.
EDIT for example, see Is getter method an alternative to volatile in Java?
EDIT to avoid confusions: This question is about cache invalidation! If two threads operate on the same object, the fields of the objects can be cached (per thread), if they are not declared volatile. How can I guarantee that the cache is invalidated properly?
FINAL EDIT Thanks to @Peter Lawrey who pointed me to JLS §17 (Java memory model). As far as I see, it states that synchronization establishes a happens-before relation between operations, so that a thread sees the updates from another thread if those updates "happened-before", e.g. if getter and setter for a non-volatile field are synchronized
.
Merely a synchronization on the methods which access said field is insufficient
- no, synchronization is "stronger" thanvolatile
. It means you won't even enter the method if another thread is in it, so you only enter after the other one exited and finished changing the value. – Melisandraprivate
fields, so that all access has to be done via synchronized methods, the visibility of the most recent values is already guaranteed. As @Melisandra correctly pointed out, it will be even stronger than declaring a variablevolatile
. As the article you’ve linked points out, volatile is not always enough. – Schaaf