60

When return value is not of interest, is there any (even irrelevant in practice) difference between AtomicInteger.getAndIncrement() and AtomicInteger.incrementAndGet() methods, when return value is ignored?

I'm thinking of differences like which would be more idiomatic, as well as which would put less load in CPU caches getting synchronized, or anything else really, anything to help decide which one to use more rationally than tossing a coin.

hyde
  • 60,639
  • 21
  • 115
  • 176
  • 1
    if return value is of interest, is it possible that in the case of `AtomicInteger.getAndIncrement()` two threads will get the same value? – ffff Jul 18 '18 at 12:42
  • @FaizHalde: that should have been asked in a separate question. But no, if nothing decrements the atomic integer (and it doesn't overflow), then no two calls will observe the same value from calling `getAndIncrement`. – Joachim Sauer Aug 31 '20 at 08:19
  • @FaizHalde if 2 or more threads are in contention, "prev" or in this case "current" will be the same... but after a `compareAndSet()` only **one** thread (the winner) will return. This winner will return the version that matched the version that the thread saw at the beginning of the spin. – Delark Feb 25 '22 at 19:55
  • @FaizHalde ... All threads that are still competing will fail their `comapreAndSet()` because the version of the atomic value will no longer match the one they saw when the first `.get()` at the beginning of their respective spin-locks was made, and so they will retry, on their next spin their "current" will finally reflect the change, so the answer is: No, `AtomicInteger.getAndIncrement()` will never bring the same value even under heavy contention. – Delark Feb 25 '22 at 19:58

5 Answers5

42

Since no answer to the actual question has been given, here's my personal opinion based on the other answers (thanks, upvoted) and Java convention:

incrementAndGet()

is better, because method names should start with the verb describing the action, and intended action here is to increment only.

Starting with verb is the common Java convention, also described by official docs:

"Methods should be verbs, in mixed case with the first letter lowercase, with the first letter of each internal word capitalized."

hyde
  • 60,639
  • 21
  • 115
  • 176
  • 13
    Would be nice if they exposed a simple `increment()` method, just for the sake of readability. – Bennett Lynch Jan 31 '18 at 00:22
  • 1
    I guess the reason why they kept it like that in atomicInteger() is to "maintain the convention" as the behaviour of returning either "prev" or "next" becomes a necessity when dealing with atomic swaps. This is not useful in integers since the next will always be prev + 1 (and prev == next -1), but when dealing with objects it is extremely useful. More problematic to me is the fact that a failed compareAndSet does not give you a witness. – Delark Feb 25 '22 at 20:11
37

The code is essentially the same so it does not matter:

public final int getAndIncrement() {
    for (;;) {
        int current = get();
        int next = current + 1;
        if (compareAndSet(current, next))
            return current;
    }
}

public final int incrementAndGet() {
    for (;;) {
        int current = get();
        int next = current + 1;
        if (compareAndSet(current, next))
            return next;
    }
}
assylias
  • 321,522
  • 82
  • 660
  • 783
  • 3
    `incrementAndGet()==getAndIncrement()+1` – irreputable Feb 28 '13 at 17:24
  • 1
    @irreputable Not sure I get your point - if you don't store the returned value, `var.incrementAndGet();` and `var.getAndIncrement();` produce exactly the same result... – assylias Feb 28 '13 at 17:28
  • yes. I'm saying actually one of the methods is enough, the other is kind of redundant. – irreputable Feb 28 '13 at 17:30
  • @irreputable Ah sorry... Yes. Also I'm not sure why `incrementAndGet` does not simply call `addAndGet(1)` instead of mostly duplicating the code... – assylias Feb 28 '13 at 17:32
  • 3
    Doug Lea is obsessed with every CPU cycle:) – irreputable Feb 28 '13 at 17:33
  • @irreputable Following-up on that in [this question](http://stackoverflow.com/questions/15142546/atomicinteger-implementation-and-code-duplication). – assylias Feb 28 '13 at 18:08
11

No, there's no difference (if you don't care about the return value).

The code of those methods (in the OpenJDK) differs only in that one uses return next and the other uses return current.

Both use compareAndSet under the hood with the exact same algorithm. Both need to know both the old and the new value.

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
8

Just want to add to existing answers: there could be very small non-noticeable difference.

If you look at this implementation:

public final int getAndIncrement() {
    return unsafe.getAndAddInt(this, valueOffset, 1);
}

public final int incrementAndGet() {
    return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}

Note - both function call exactly the same function getAndAddInt, except +1 part, which means that in this implementation getAndIncrement is faster.

But, here is older implementation:

public final int getAndIncrement() {
    for (;;) {
        int current = get();
        int next = current + 1;
        if (compareAndSet(current, next))
            return current;
    }
}

public final int incrementAndGet() {
    for (;;) {
        int current = get();
        int next = current + 1;
        if (compareAndSet(current, next))
            return next;
    }
}

The only difference is return variable, so both functions perform exactly the same.

Iłya Bursov
  • 23,342
  • 4
  • 33
  • 57
0

Here I am giving an example. Hope it will clear your doubt.

Suppose I have a variable i as

AtomicInteger i = new AtomicInteger();

In this case:

i.getAndIncrement() <==> i++;

And

i.incrementAndGet() <==> ++i;

Please have a look of the below programs

public class Test1
{   
    public static void main(String[] args) 
    {               
        AtomicInteger i = new AtomicInteger();
        System.out.println(i.incrementAndGet());  
        System.out.println(i);  

    }

}

**output

1 1 ======================================**

public class Test2
{   
    public static void main(String[] args) 
    {               
        AtomicInteger i = new AtomicInteger();
        System.out.println(i.getAndIncrement());  
        System.out.println(i); 

    }

}

**output

0 1 -------------**

Comment: 1) In the class Test1, incrementAndGet() will first increment the i value and then print.

2) In the class Test2, getAndIncrement() will first print the i value and then increment.

That's all.

Ajju_bhai
  • 19
  • 1
  • 1
    Thanks for your answer. However, in your answer, the result is actually used (printed). The question is about a situation where *"When return value is not of interest"*... – hyde Jun 05 '17 at 07:18