21

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?

Community
  • 1
  • 1
David Grant
  • 13,929
  • 3
  • 57
  • 63
  • Since one has mentioned it (neither here nor on the duplicate): w/ Atomic classes you have a nifty method lazySet. On most architectures it outperforms basic volatile write (but it doesn't have the same semantics). Basically lazySet doesn't need to flush the CPU write buffers which is pretty good as they can be flushed while the CPU is stalled. – bestsss Oct 19 '12 at 11:30

4 Answers4

21

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);
assylias
  • 321,522
  • 82
  • 660
  • 783
17

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.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
10

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.

Gray
  • 115,027
  • 24
  • 293
  • 354
7

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.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • *"it's very easy to write code which doesn't always work as expected."* => Could you be more specific? Do you mean people assuming volatile gives atomicity guarantees for example? – assylias Oct 12 '12 at 13:02
  • 1
    @assylias: I added some examples to my answer. – Aaron Digulla Oct 12 '12 at 13:33
  • if you have races w/ volatile you are going to have them w/ atomic classes just as much. now that standard argument: counters. Using atomic classes as counters is not scalable anyways. While the modification of the atomic are to be well 'atomic' the data races still remain. – bestsss Oct 19 '12 at 11:23
  • @bestsss: If you know exactly how `volatile` works, you can use it. But I bet that most of the Java developers out there don't, so I don't encourage anyone to use it. – Aaron Digulla Oct 29 '12 at 10:17