xyz
xyz

Reputation: 5407

AtomicInteger calculation in a loop

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

I found that the increment method works within a loop block. Why can't we just calculate a result without any looping? What is sence on it?

Upvotes: 0

Views: 2130

Answers (4)

Peter Lawrey
Peter Lawrey

Reputation: 533472

Consider you have three threads T1, T2, T3 running

T1: int current = get(); == 0
T2: int current = get(); == 0
T3: int current = get(); == 0
T3: int next = current + 1;
T1: int next = current + 1;
T2: int next = current + 1;
T2: if (compareAndSet(current, next)) // true
T2:     return current;
T3: if (compareAndSet(current, next)) // false
T1: if (compareAndSet(current, next)) // false

T1 and T3 need to try again, and only one might succeed the second time.

Upvotes: 1

Jilles van Gurp
Jilles van Gurp

Reputation: 8274

compareAndSet might fail if another thread is updating. The for(;;) is a bit weird, I would have gone for while(true).

This is called optimistic locking.

Upvotes: 1

Zim-Zam O'Pootertoot
Zim-Zam O'Pootertoot

Reputation: 18148

It's possible for the call to compareAndSet to return false if another thread increments or otherwise modifies the AtomicInteger at the same time that the current thread is incrementing the AtomicInteger

  1. current thread calls current = get()
  2. another thread modifies the AtomicInteger
  3. current thread calls next = current + 1
  4. current thread calls if(compareAndSet(current, next))

On step 4, the call to compareAndSet will return false and will leave the AtomicInteger unchanged because current will not match the current value of the AtomicInteger (due to another thread having modified it on step 2); therefore the method loops and tries again

Upvotes: 6

Jeffrey
Jeffrey

Reputation: 44808

If another thread came along and changed the value of AtomicInteger between int current = get() and compareAndSet(current, next), then the compareAndSet call would fail. Using a loop ensures that this possibility will never happen.

Upvotes: 6

Related Questions