The key to understanding this is to understand what compareAndSet() does:
/** * Atomically sets the value to the given updated value * if the current value {@code ==} the expected value. * * @param expect the expected value * @param update the new value * @return true if successful. False return indicates that * the actual value was not equal to the expected value. */ public final boolean compareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); }
In Unsafe.java:
/** * Atomically update Java variable to <tt>x</tt> if it is currently * holding <tt>expected</tt>. * @return <tt>true</tt> if successful */ public final native boolean compareAndSwapInt(Object o, long offset, int expected, int x);
So this method uses JVM internals to atomically:
- check whether the value has the expected value
- if not, do nothing and return false
- if so, set to the new value and return true
The loop you've found exits when compareAndSet() returns true.
for (;;) { int current = get(); int next = current + 1; if (compareAndSet(current, next)) return current; }
... is equivalent to:
boolean done = false; int current; while(!done) { current = get(); int next = current + 1; done = compareAndSet(current, next); } return current;
... but slightly terser and cleaner.
public synchronized int getAndIncrement() { return value++; }how is this any different?