>  기사  >  Java  >  Java 원자 연산 클래스 소스 코드 분석

Java 원자 연산 클래스 소스 코드 분석

WBOY
WBOY앞으로
2023-04-21 11:31:071298검색

먼저 소스 코드의 일부를 살펴보겠습니다.

public class AtomicLong extends Number implements java.io.Serializable {
    private static final long serialVersionUID = 1927816293512124184L;

    //1.获取Unsafe类实例
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    //2.存放value的偏移量
    private static final long valueOffset;
    static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();

    //3.用于判断是否支持Long类型无锁CAS
    private static native boolean VMSupportsCS8();

    static {
        try {
            //4.获取value在AtomicLong中的偏移量
            valueOffset = unsafe.objectFieldOffset
                (AtomicLong.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }
    //5.实际变量值
    private volatile long value;

    /**
     * Creates a new AtomicLong with the given initial value.
     *
     * @param initialValue the initial value
     */
    public AtomicLong(long initialValue) {
        value = initialValue;
    }
    ············省略部分代码·············
}

위 코드에서 Unsafe 클래스의 인스턴스는 코드 1에서 Unsafe.getUnsafe()를 통해 획득됩니다(AtomicLong 클래스가 rt.class 아래에 있기 때문입니다). jar 패키지이며 AtomicLong 클래스는 Bootstarp 클래스 로더에 의해 Loaded로 전달됩니다. 코드 5에서는 메모리 가시성을 보장하기 위해 값이 휘발성 유형으로 선언됩니다. 코드 2와 4를 통해 AtomicLong 클래스의 값 변수의 오프셋을 가져옵니다.

다음으로 AtomicLong의 주요 함수를 소개하겠습니다.

  • 증가 및 감소 코드

//调用unsafe方法,设置value=value+1后,返回原始的值
public final long getAndIncrement() {
    return unsafe.getAndAddLong(this, valueOffset, 1L);
}

//调用unsafe方法,设置value=value-1后,返回原始的值
public final long getAndDecrement() {
    return unsafe.getAndAddLong(this, valueOffset, -1L);
}


//调用unsafe方法,设置value=value+1后,返回递增后的值
public final long incrementAndGet() {
    return unsafe.getAndAddLong(this, valueOffset, 1L) + 1L;
}

//调用unsafe方法,设置value=value-1后,返回递减后的值
public final long decrementAndGet() {
    return unsafe.getAndAddLong(this, valueOffset, -1L) - 1L;
}

위의 네 가지 함수는 Unsafe의 getAndAddLong 메서드를 호출하여 내부적으로 구현됩니다. 여기서 첫 번째 매개 변수는 다음과 같습니다. AtomicLong 인스턴스에 대한 참조이며, 두 번째 매개변수는 AtomicLong에 있는 value 변수의 오프셋 값이고, 세 번째 매개변수는 설정할 두 번째 변수의 값입니다.

JDK7에서 getAndIncrement() 메서드의 구현 논리는 다음과 같습니다.

public final long getAndIncrement() {
    while(true) {
        long current = get();
        long next = current + 1;
        if (compareAndSet(current, next))
            return current;
    }
}

위 코드에서 각 스레드는 먼저 변수의 현재 값을 가져옵니다(값은 휘발성 변수이므로 얻은 가장 최근 값입니다). 그런 다음 작업 메모리에서 1씩 증가시킨 다음 CAS를 사용하여 변수 값을 수정합니다. 설정이 실패하면 설정이 성공할 때까지 루프가 계속 시도됩니다.

JDK8의 논리는

public final long getAndIncrement() {
        retrturn unsafe.getAndAddLong(this, valueOffset, 1L);
    }

JDK8의 unsafe.getAndAddLong 코드는

public final long getAndAddLong(Object var1, long var2, long var4) {
   long var6;
   do {
       var6 = this.getLongVolatile(var1, var2);
   } while(!this.compareAndSwapLong(var1, var2, var6, var6 + var4));

   return var6;
}

JDK7의 AtomicLong에 있는 루프 논리가 원자 연산 클래스인 Unsafe로 대체되었음을 알 수 있습니다. JDK8 내장.

  • boolean CompareAndSet(long Expect, long update)

public final boolean compareAndSet(long expect,long update) 
{
    return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
}

함수는 내부적으로 unsafe.compareAndSwapLong 메서드를 호출합니다. 원자 변수의 값이 예상과 같으면 업데이트 값을 사용하여 값을 업데이트하고 true를 반환하고, 그렇지 않으면 false를 반환합니다.

위 내용은 Java 원자 연산 클래스 소스 코드 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제