And then I am using volatile
, so it will guarantee the consistent view of the variable across all threads.
Thread-safety is already guaranteed by atomic variables. volatile
is redundant if you won't reassign the variable. You can replace volatile
with final
here:
private final AtomicInteger atomInt = new AtomicInteger(3);
Does it mean that I have got complete thread safety or still there are chances of "memory consistency issues"?
At this moment, it's absolutely thread-safe. No "memory consistency issues" might happen with the variable. But using proper thread-safe components doesn't mean that the whole class/program is thread-safe. Problems might take place if interactions between them are incorrect.
Using volatile variables reduces the risk of memory consistency errors ...
volatile
variables can only guarantee visibility. They don't guarantee atomicity.
As Brian Goetz writes (emphasis mine):
volatile
variables are convenient, but they have limitations. The most common use for volatile variables is as a completion, interruption, or status flag. Volatile variables can be used for other kinds of state information, but more care is required when attempting this. For example, the semantics of volatile
are not strong enough to make the increment operation (count++
) atomic, unless you can guarantee that the variable is written only from a single thread.
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 variable does not participate in invariants with other state variables;
- Locking is not required for any other reason while the variable is being accessed.
From the docs of the java.util.concurrent.atomic
package:
get
has the memory effects of reading a volatile
variable.
set
has the memory effects of writing (assigning) a volatile
variable.