Possible Duplicate:
Java: volatile boolean vs AtomicBoolean
When is it appropriate to use a volatile
primitive (e.g. boolean
, integer
or long
) instead of AtomicBoolean
, AtomicInteger
or AtomicLong
, and vice-versa?
Possible Duplicate:
Java: volatile boolean vs AtomicBoolean
When is it appropriate to use a volatile
primitive (e.g. boolean
, integer
or long
) instead of AtomicBoolean
, AtomicInteger
or AtomicLong
, and vice-versa?
The visibility semantics are exactly the same, the situation where using the atomic primitives is useful is when you need to use their atomic methods.
For example:
if (volatileBoolean) {
volatileBoolean = !volatileBoolean;
}
could create issues in a multi threaded environment as the variable could change between the two lines. If you need the test&assignment to be atomic, you can use:
atomicBoolean.compareAndSet(true, false);
Using a plain volatile is simpler and more efficient if all you want to do is set or get the value. (But not get&set the value)
If you want more operations like getAndIncrement or compareAndSwap you need to use the AtomicXxxx classes.
The Atomic*
classes wrap a volatile
primitive of the same type. From the source:
public class AtomicLong extends Number implements java.io.Serializable {
...
private volatile long value;
...
public final long get() {
return value;
}
...
public final void set(long newValue) {
value = newValue;
}
So.
When is it appropriate to use a volatile primitive (e.g. boolean, integer or long) instead of AtomicBoolean, AtomicInteger or AtomicLong
If all you are doing is getting and setting a Atomic*
then you might as well just have a volatile
field instead.
... and vice-versa?
What the Atomic*
classes give you however, are methods that provide more advanced functionality such as incrementAndGet()
, compareAndSet()
, and others that implement multiple operations (get/increment/set, test/set) without locking. That's why the Atomic*
classes are so powerful.
It's also important to note that wrapping your volatile
field using Atomic*
class is a good way to encapsulate the critical shared resource from an object standpoint. This means that developers can't just deal with the field assuming it is not shared possibly injecting problems with a field++;
or other code that introducing race conditions.
We have started to ban the use of volatile
in our sources because it's very easy to write code which doesn't always work as expected.
In my experience, people add volatile to share a value between threads. And then, someone else starts to modify the value. And most of the time, this works. But in production, you start to get odd errors which are really hard to track down. Counters are incremented 100'000 times (tests only increment them 10 times) but end up at 99'997. In Java 1.4, long values could get corrupted really, really rarely.
The Atomic*
helper classes, on the other hand, impose only a small overhead and they always work as advertised.
So unless you have a very good reason(*) to use volatile
, always prefer the Atomic*
helper classes.
If you don't know exactly what each character in the Atomic*
helper classes does, then you should really avoid volatile
.
*: Premature optimization is never a good reason.