3

From documentation page:

Package java.util.concurrent.atomic Description:

A small toolkit of classes that support lock-free thread-safe programming on single variables. In essence, the classes in this package extend the notion of volatile values, fields, and array elements to those that also provide an atomic conditional update operation of the form

boolean compareAndSet(expectedValue, updateValue);

With many options available in atomic package like

AtomicBoolean
AtomicInteger
AtomicLongArray

etc, can I use these AtomicXXX and slowly get rid of volatile variables in my legacy code?

EDIT:

  1. Keep volatile for single write & multiple read operations in different threads (my conclusion after reading many articles), multi-writer, single-reader cases ( as per @erickson comments)
  2. Use AtomicXXX for multiple updates & multiple reads among multiple threads to avoid synchronization. Provide atomicity to volatile variables.

My thought process has been changed with @ericksoncomments.volatile supports multiple write & single read` but can fail with multiple writes and multiple reads. I am confused on this concept.

Ravindra babu
  • 37,698
  • 11
  • 250
  • 211
  • No. They're not a replacement for `volatile`, they're a replacement for protecting single variables with locks. – OrangeDog May 17 '16 at 16:41
  • If that is the case, where should I use volatile variable? Only single write and multiple read operations? – Ravindra babu May 17 '16 at 16:46
  • When an assignment to the variable must be seen immediately by all threads, and that's not already guaranteed by another synchronisation mechanism: [Do you ever use the volatile keyword in Java?](http://stackoverflow.com/a/106787/476716) – OrangeDog May 17 '16 at 16:49
  • Also: [Does volatile influence non-volatile variables?](http://stackoverflow.com/q/6167404/476716) – OrangeDog May 17 '16 at 16:55
  • @OrangeDog, the Javadoc for the `java.util.concurrent.atomic` package says, "The memory effects for accesses and updates of atomics generally follow the rules for volatiles" (https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/package-summary.html) – Solomon Slow May 17 '16 at 16:59
  • @jameslarge yes, which is good, but does not mean that `volatile` is now "legacy" or should always be replaced. – OrangeDog May 17 '16 at 17:00
  • @OrangeDog I don't think either are true. If you need simple read/write semantics then use volatile. If you need more complex, conditional, writes then use an AtomicXXX. – John Vint May 17 '16 at 17:25
  • @JohnVint do you mean either of the things that I said weren't true? – OrangeDog May 17 '16 at 17:28
  • @OrangeDog It is opinionated, but I don't think either need to be true, so yes, based on my opinion. I don't think volatile is legacy, nor do I think all previously volatile fields should be replaced with an Atomic counterpart. – John Vint May 17 '16 at 17:33
  • @Ravindrababu AtomicXXX classes are really good when you have a write which changes based off the values. For instance, if you have an `AtomicBoolean` flag in which you only want to set it to true by a single thread, if you have multiple threads running `if(flag) { flag = false } ` many threads can succeed where you may only want one. With `if(flag.compareAndSet(true, false))` only one thread will succeed. – John Vint May 17 '16 at 17:50

1 Answers1

4

Yes, an AtomicXXX instance provides the same visibility guarantees that you get from accessing a volatile field.

However, AtomicXXX do more than volatile fields, and accordingly, they are a bit more expensive to use. Specifically, they provide operations that are more like an optimized synchronized block than a volatile read or write. You increment-and-get, or compare-and-swap—multiple actions, atomically. Volatile variables don't provide any atomicity.

So, switching from volatile to AtomicXXX isn't necessarily a good move. Consider if it makes sense given how data are used, and perhaps do some profiling on a prototype to see what performance impact it will have.

erickson
  • 265,237
  • 58
  • 395
  • 493
  • @Ravindrababu Any field that is read and written by multiple threads needs a memory barrier like `volatile` to ensure visibility; but `volatile` is only sufficient if the field can be modified independently from all other fields. It's not limited to single-writer, multiple-reader situations. It could also be used in multi-writer, single-reader cases. – erickson May 17 '16 at 16:54
  • Does not multi write cause inconsistency unless it is protected by lock? Sorry if I did not catch your point correctly. – Ravindra babu May 17 '16 at 16:58
  • If `atomicInteger.get()` and `atomicInteger.set(n)` are more expensive than `m=myVolatile` and `myVolatile=n`, it's not because the `addAndGet` or `compareAndSet` methods _exist_. It's probably because `get()` and `set()` are method calls. – Solomon Slow May 17 '16 at 17:11
  • @Ravindrababu a lock acquire and release has the same memory semantics as a volatile write and read or an AtomicXXX write and read. – John Vint May 17 '16 at 17:27
  • @Ravindrababu If your program is correct using `AtomicXXX.get()` and `AtomicXXX.set()` only, it will be correct using `volatile`. If you need to use `synchronized` in around some read-write combinations (like `x++`) to make your program correct, then the `java.util.concurrent.atomic` package may offer a more efficient alternative. Atomic types are a closer parallel to `synchronized` keyword than `volatile`. – erickson May 18 '16 at 18:38