简体   繁体   中英

AtomicReference vs AtomicReferenceFieldUpdater, what's a purpose of AtomicReferenceFieldUpdater?

I'd like to atomically upgrade my reference. For example to use compareAndSet , getAndSet and other atomic operations.

I came from C++, so in C++ I've got volatile keyword and different atomic intrinsics, or the <atomic> API . In java, there's also a volatile keyword and different unsafe atomic operations .

By the way, there's also a well-documented AtomicReference (as well as Long , Integer , Boolean ), so JDK creators provided us a way to safely execute atomic operations against references and primitives. There's nothing wrong about the API, it is rich and seems very familiar.

But, there's also an AtomicReferenceFieldUpdater whick provides a kinda weird way to execute atomic operations: you have to "find" the field via reflection by name and then you can use exactly the same operations.

So my questions are:

  1. What's the purpose of AtomicReferenceFieldUpdater at all? In my opinion it is implicit and kinda weird: you need to declare a volatile variable filed AND and the field updater itself. So where should I use a FieldUpdater ?
  2. It provides an indirection: you're manipulating (not changing !) the FieldUpdater , not the variable, this confuses.
  3. Performance: as far as I know, both AtomicReferenceFieldUpdater and AtomicReference are delegating to the Unsafe, so their performance is similar, but anyway: are there any performance penalties of FieldUpdater agaist Reference?

It's used to save memory.

Example from the doc:

class Node {
   private volatile Node left, right;

   private static final AtomicReferenceFieldUpdater<Node, Node> leftUpdater =
     AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "left");
   private static AtomicReferenceFieldUpdater<Node, Node> rightUpdater =
     AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right");

   Node getLeft() { return left; }
   boolean compareAndSetLeft(Node expect, Node update) {
     return leftUpdater.compareAndSet(this, expect, update);
   }
   // ... and so on
 }

it declares left and right as Node directly. And the AtomicReferenceFieldUpdater is static final .

Without AtomicReferenceFieldUpdater , you might need declare them as AtomicReference<Node> .

private  AtomicReference<Node> left, right;

which consumes more memory than Node . When there are many instances of Node , it consumes much more memory than first approach.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM