From book “Java Concurrency in Practice” page 26:
You can use volatile variables only when all the following criteria are met:
-
Writes to the variable do not depend on its current value, or you can ensure that only a single thread ever updates the value;
-
The variabledoes not participate in invariants with other state variables; and
- Locking is not required for any other reason while the variable is being accessed.
How to comprehend “The variable does not participate in invariants with other state variables when using volatile keyword“?
A simple definition of “invariant”: a condition that is always true during the lifetime of an object.
That’s why you can’t use them within a class that has invariants that relate multiple variables.
For example imagine you have a
classto model a time interval described by two variables:startandend. An invariant condition may be thatstartis always less or equal thanend. If both variables (just as example) are declared as volatile then you can rely on visibility features ofvolatilebut you can’t be sure that during a change that involves both variables the invariant is always satisfied. Think:In this case you can be sure that the change is visible to every thread but in the middle of the two instructions the object state could be not valid. Because it can be accessed by other threads (remember this is a simple case so it’s possible but not likely) then the invariant condition “start < end” could be broken.
That’s why the use of volatile is somehow discouraged outside a (small) set of well defined patterns. A volatile variable should be used only if these conditions are satisfied:
For example the expression
int a = i++;isn’t atomic then it’s not – strictly speaking – thread-safe because it’ll be rewritten with something like this:To make it atomic from a thread point of view you can imagine a class like this:
Of course it exists a true implementation of this
AtomicIntegerand it’s part of the package java.util.concurrent.atomic, it provides some simple basic routines for lock-free concurrent programming.