【不简单的Atomic工具】getAndAddInt in getAndIncrement

上一篇Atmoic文章中提到,JDK8在AtomicIntegergetAndIncrement方法实现上发生了变化:

JDK7
1
2
3
4
5
6
7
8
public final int getAndIncrement() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return current;
}
}
JDK8
1
2
3
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}

getAndAddInt

1
2
3
4
5
6
7
public final int getAndAddInt(Object paramObject, long paramLong, int paramInt) {
int i;
do
i = getIntVolatile(paramObject, paramLong);
while (!(compareAndSwapInt(paramObject, paramLong, i, i + paramInt)));
return i;
}

1
2
3
4
5
6
7
8
jint
sun::misc::Unsafe::getIntVolatile (jobject obj, jlong offset)
{
volatile jint *addr = (jint *) ((char *) obj + offset);
jint result = *addr;
read_barrier ();
return result;
}

汇编之后

1
2
3
0x0000000002c207f5: lock cmpxchg %r8d,0xc(%rdx)
0x0000000002c207fb: sete %r11b
0x0000000002c207ff: movzbl %r11b,%r11d
1
2
3
0x0000000002cf49c7: mov %rbp,0x10(%rsp)
0x0000000002cf49cc: mov $0x1,%eax
0x0000000002cf49d1: lock xadd %eax,0xc(%rdx)

原本的lock cmpxchglock xadd所替换,也就是在1.8之后,在硬件支持lock XADD这样的操作情况下,都会用fetch-and-add来替换CAS操作。

参考: