package com.ruigege.AtomicOperationClass4;
import java.util.concurrent.atomic.AtomicLong;
import jdk.internal.misc.Unsafe;
import java.lang.Number;
public class AtomicLongTest extends Number implements java.io.Serializable{
private static final long serialVersionUID = 1927816293512124184L;
private static final Unsafe unsafe = Unsafe.getUnsafe();
private volatile long value;//用於放實際值的變量
private final long valueOffset;//value的偏移量
static {
try {
valueOffset = unsafe.objectFieldOffset(AtomicLong.class.getDeclaredField(value));
}catch(Exception e) {
throw new Error(e);
}
}
public AtomicLongTest(long initialValue) {
value = initialValue;
}
//下面的語句是用於判斷JVM是否支持Long類型的CAS
static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
private static native boolean VMSupportCS8();
/**
* 該方法使用CAS算法用於累加
* @return
*/
public final long incrementAndGet() {
return unsafe.getAndAddLong(this, valueOffset, 1L) + 1L;
}
/**
* 咱們來一塊兒回顧一下Unsafe類中的成員方法getAndAddLong方法
* public final long getAndAddLong(Object obj,long offset,long addValue){
* long l;
* do{
* l = getLongvolatie(obj,offset);//獲取obj對象偏移量爲offset的值
* }(!compareAndSwapLong(obj,offset,l,l+addValue));如與預期不相同,那麼咱們不斷地獲取l的值,若是
* //相同了,說明這個時候能夠+addValue將獲得的值賦值給l就能夠了
* return l;最後返回的是+addValue以前的值
* //我理解的CAS算法,其實它的本質就是不斷循環獲取一致的值,再進行更新。
* }
*/
/**
* 該方法使用CAS用於累減
* @return
*/
public final long decrementAndGet() {
return unsafe.getAndAddLong(this,valueOffset,-1L) -1L;
}
/**
* 下面這兩個方法,能夠和上面的兩個方法做對比,都是累加,可是上面返回是累加以後的值,下面是返回累加以前的值
* @return
*/
public final long getAndIncrement() {
return unsafe.getAndAddLong(this, valueOffset, 1L);
}
public final long getAndDecrement() {
return unsafe.getAndAddLong(this,valueOffset,-1L);
}
/**
* 下面這個方法相似於Unsafe中的compareAndSwapLong方法
* @param expect
* @param update
* @return
*/
public final boolean compareAndSet(long expect,long update) {
return unsafe.compareAndSwapLong(this,valueOffset,expect,update);
}
}
public final int getAndIncrement(){
while(true){
long temp = get();//這一行就是或者value的值
long newTemp = temp + 1;
if(compareAndSet(temp,newTemp){
//這裏面的判斷是使用了該類裏面測成員方法
return temp;
}
}
}
atomicLong的困境以及若是優化:AtomicLong類的問題在於,在高併發的狀況下,全部的線程都會區競爭同一個共享變量,而且根據CAS機制,最後只有一個線程可以更新成功,這就致使了,其餘線程爲了獲取共享變量,會進入到無限循環的自旋中;引入LongAdder類就是把一個共享變量分紅爲了多個共享變量,那麼線程去競爭的時候,壓力會小一些,每一個線程競爭到共享變量的可能性大大增長。 java
基本構成:LongAdder內部是由一個Cell數組(須要初始化時纔會建立數組,沒有初始化時爲null)和一個base變量,當建立該類實例之後,共享變量會變成多個Cell對象(共享變量被Cell類封裝了),而後在高併發下,線程能夠競爭的共享變量(Cell實例)就變多了,而且一個線程若是沒有獲取到Cell實例,並不會進入到自旋狀態下,而是去競爭其餘Cell;LongAdder實例的值,就是個各個Cell值累加,在加上base變量的值。該類其內部數組是一個延遲初始化原子性更新數組,屬於惰性加載;git
當一開始判斷Cell數組時null時,全部累加操做都是在base變量上的,保持Cell數組的大小是2的N次方,在初始化數組的時候,大小爲2,裏面的元素是Cell實例,這個是一個Atomic改進類,用於解決僞共享問題github
變量加載時的提高原理:對於大多數孤立的多個資源子操做進行字節填充是浪費,可是 LongAdder實例的數組能夠是內存連續,所以咱們須要添加個@sun.misc.Contended註解對Cell類進行填充,這樣按行加載內存機制就獲得優化,提高性能。web
詳細原理咱們下次再說算法
https://github.com/ruigege66/ConcurrentJava