1 关于AtomicInteger
AtomicInteger 是一种基于支持原子操作的类,我们日常使用的方法包括
使用场景1
AtomicInteger i= new AtomicInteger(1);
invoiceInfos.forEach(o->{
InvoiceToWordDto invoiceToWordDto=new InvoiceToWordDto();
invoiceToWordDto.setAmount(o.getTotalAmt().toString());
invoiceToWordDto.setPayDate(DateUtils.parseDateToStr(DateUtils.YYYYMMDD,o.getPayAmtDate()));
invoiceToWordDto.setSupplyName(financingInfo.getCoreEnterpriseName());
invoiceToWordDto.setNum(i.getAndIncrement());
bigLists.add(invoiceToWordDto);
});
java 的lamda表达式,需要原子操作的实现。
实现这样一种递增的顺序序号赋值。getAndIncrement();
那么它是怎样实现的呢?
2 AtomicInteger源码
/**
* Atomically increments by one the current value.
*
* @return the previous value
*/
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
通过unsafe去操作,cpu直接去操作底层的指令
原理1.Unsafe是CAS的核心类,由于Java方法无法直接访问底层系统,需要通过本地(native)方法来访问,Unsafe类相当于Java留的一个后门,基于该类可以直接操作特定内存的数据。Unsafe类存在于jdk的sun.misc包中,其内部方法操作可以像C的指针一样直接操作内存,CAS操作的执行依赖于Unsafe类的方法。
注意Unsafe类中的所在方法都是native修饰的,也就是送Unsafe类中的方法都直接调用操作系统底层资源执行相应任务,故可以直接比较内存值和期望值.而其value值被volatile修饰后保证了其可见性,一旦发生偏移就会通知本地内存
原理2.变量valueOffset,表示该变量值在内存中的偏移地址,因为Unsafe就是根据内存偏移地址获取数据的,如果是1 就是增大,-1就是减小。
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
public final int getAndDecrement() {
return unsafe.getAndAddInt(this, valueOffset, -1);
}
public final int getAndAdd(int var1) {
return unsafe.getAndAddInt(this, valueOffset, var1);
}
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
public final int decrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
}
public final int addAndGet(int var1) {
return unsafe.getAndAddInt(this, valueOffset, var1) + var1;
}
public final int getAndUpdate(IntUnaryOperator var1) {
int var2;
getAndAddInt的底层是
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
var5 = this.getIntVolatile(var1, var2);
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
return var5;
}
就是CAS。