3

In one of my programs, I was trying to update the value of an Atomic Integer, but could not decide between set() and getAndSet() methods because they both seem to do the same. I have already gone through this and this post, but they are comparing set and compareAndSet(which gives up setting the provided value, if the thread doesn't have the expected value) whereas I am interested to compare set with setAndGet(which returns only after setting the provided value).

   //Sets the newValue to the volatile member value
    public final void set(int newValue) {
       value = newValue;
   }

and

   public final int getAndSet(int newValue) {
       return unsafe.getAndSetInt(this, valueOffset, newValue);
   }
    //Doesn't give up until it sets the updated value. So eventually overwrites  the latest value.
    public final int getAndSetInt(Object paramObject, long paramLong, int paramInt) {
    int i;
    do {
        i = getIntVolatile(paramObject, paramLong);
    } while (!compareAndSwapInt(paramObject, paramLong, i, paramInt));
    return i;
}

I am not able to find out any major difference between the two methods.

  1. Why have set() when we have getAndSet(). One may choose to not use the value returned by getAndSet().

  2. When should one use each of these methods?

Steve
  • 889
  • 1
  • 12
  • 26

1 Answers1

1

According to the java documentation, they both do different things:

AtomicReference#getAndSet will set the internal value to whatever you pass in, but will return the old value.

AtomicReference<Integer> reference = new AtomicReference<>(10);
int value = reference.getAndSet(14);
System.out.println(value); // prints 10

AtomicReference#set will set the internal value, and that's it. It returns void.

AtomicReference<Integer> reference = new AtomicReference<>(10);
reference.set(15);
System.out.println(reference.get()); // prints 15;
Frontear
  • 1,150
  • 12
  • 25
  • So, why have `set()` when we have `getAndSet()`. One may choose to not use the value returned by `getAndSet()`. – Steve Apr 24 '19 at 13:19
  • Cases can differ. For some, it's more time consuming to write `int last = reference.get(); doSomethingWithLastReference(last); reference.set(15);`. It makes more sense to be able to do it in one go (and reduces the amount you need to type). – Frontear Apr 24 '19 at 13:21
  • 2
    Note that invoking 'get' then invoking 'set' is not equivalent to invoking 'getAndSet': 'getAndSet' is atomic. One is guaranteed to obtain the value mostly recently assigned to the atomic variable with 'getAndSet'. That guarantee does not exist when making two invocations. – Thomas Bitonti Apr 24 '19 at 14:34
  • Whether to use 'set' or 'getAndSet' depends on intent and style. In many cases, 'set' (or 'getAndSet') simply more clearly expresses what the program is to do. But, if you are trying to avoid destructive operations, then you would use 'getAndSet', and would then likely wrap that in an explicit destructive operation: 'explicitDestroy( atomicVar.getAndSet( newValue ) )'. Note that if you turn compiler warning up very high, you will get a warning if you use 'getAndSet' and do nothing with the return value. – Thomas Bitonti Apr 24 '19 at 14:57