Глядя на реальную реализацию, я имею в виду, что смотреть на код гораздо лучше, чем какой-то микробенчмарк (который менее чем бесполезен в Java или любой другой среде выполнения GC), я не удивлен, что он «значительно быстрее».Он в основном выполняет неявную синхронизированную секцию.
/**
* Atomically sets to the given value and returns the previous value.
*
* @param newValue the new value
* @return the previous value
*/
public final boolean getAndSet(boolean newValue) {
for (;;) {
boolean current = get();
if (compareAndSet(current, newValue))
return current;
}
}
/**
* 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(boolean expect, boolean update) {
int e = expect ? 1 : 0;
int u = update ? 1 : 0;
return unsafe.compareAndSwapInt(this, valueOffset, e, u);
}
А затем из com.sun.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);
в этом нет ничего волшебного, конфликт ресурсов является сукой и очень сложным.Вот почему использование final
переменных и работа с неизменяемыми данными так распространены в реальных параллельных языках, таких как Erlang.Вся эта сложность, которая потребляет процессорное время, пропущена или, по крайней мере, сдвинута куда-то менее сложная.