Reputation: 5407
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
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
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
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
current = get()
AtomicInteger
next = current + 1
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
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