Java volatile reference vs. AtomicReference

后端 未结 6 1060
慢半拍i
慢半拍i 2020-11-28 02:06

Is there any difference between a volatile Object reference and AtomicReference in case I would just use get() and set()-

相关标签:
6条回答
  • 2020-11-28 02:48

    AtomicReference provides additional functionality which a plain volatile variable does not provide. As you have read the API Javadoc you will know this, but it also provides a lock which can be useful for some operations.

    However, unless you need this additional functionality I suggest you use a plain volatile field.

    0 讨论(0)
  • 2020-11-28 02:51

    Sometimes even if you only use gets and sets, AtomicReference might be a good choice:

    Example with volatile:

    private volatile Status status;
    ...
    public setNewStatus(Status newStatus){
      status = newStatus;
    }
    
    public void doSomethingConditionally() {
      if(status.isOk()){
        System.out.println("Status is ok: " + status); // here status might not be OK anymore because in the meantime some called setNewStatus(). setNewStatus should be synchronized
      }
    }
    

    The implementation with AtomicReference would give you a copy-on-write synchronization for free.

    private AtomicReference<Status> statusWrapper;
    ...
    
    public void doSomethingConditionally() {
      Status status = statusWrapper.get();
      if(status.isOk()){
        System.out.println("Status is ok: " + status); // here even if in the meantime some called setNewStatus() we're still referring to the old one
      }
    }
    

    One might say that you could still could have a proper copy if you substituted:

    Status status = statusWrapper.get();
    

    with:

    Status statusCopy = status;
    

    However the second one is more likely to be removed by someone accidentally in the future during "code cleaning".

    0 讨论(0)
  • 2020-11-28 02:57

    JDK source code is one of the best ways to answers confusions like this. If you look at the code in AtomicReference, it uses a volatie variable for object storage.

    private volatile V value;
    

    So, obviously if you are going to just use get() and set() on AtomicReference it is like using a volatile variable. But as other readers commented, AtomicReference provides additional CAS semantics. So, first decide if you want CAS semantics or not, and if you do only then use AtomicReference.

    0 讨论(0)
  • 2020-11-28 03:03

    Short answer is: No.

    From the java.util.concurrent.atomic package documentation. To quote:

    The memory effects for accesses and updates of atomics generally follow the rules for volatiles:

    • get has the memory effects of reading a volatile variable.
    • set has the memory effects of writing (assigning) a volatile variable.

    By the way, that documentation is very good and everything is explained.


    AtomicReference::lazySet is a newer (Java 6+) operation introduced that has semantics unachievable through volatile variables. See this post for more information.

    0 讨论(0)
  • 2020-11-28 03:07

    There are several differences and tradeoffs:

    1. Using an AtomicReference get/set has the same JMM semantics as a volatile field(as the javadoc states), but the AtomicReference is a wrapper around a reference, so any access to the field involves a further pointer chase.

    2. The memory footprint is multiplied (assuming a compressed OOPs environment, which is true for most VMs):

      • volatile ref = 4b
      • AtomicReference = 4b + 16b (12b object header + 4b ref field)
    3. AtomicReference offers a richer API than a volatile reference. You can regain the API for the volatile reference by using an AtomicFieldUpdater, or with Java 9 a VarHandle. You can also reach straight for sun.misc.Unsafe if you like running with scissors. AtomicReference itself is implemented using Unsafe.

    So, when is it good to choose one over the other:

    • Only need get/set? Stick with a volatile field, simplest solution and lowest overhead.
    • Need the extra functionality? If this is a performance(speed/memory overhead) sensitive part of your code make a choice between AtomicReference/AtomicFieldUpdater/Unsafe where you tend to pay in readability and risk for your performance gain. If this not a sensitive area just go for AtomicReference. Library writers typically use a mix of these methods depending on targeted JDKs, expected API restrictions, memory constraints and so on.
    0 讨论(0)
  • 2020-11-28 03:09

    No, there is not.

    The additional power provided by AtomicReference is the compareAndSet() method and friends. If you do not need those methods, a volatile reference provides the same semantics as AtomicReference.set() and .get().

    0 讨论(0)
提交回复
热议问题