클래스를 사용하여 AtomicXXX 시리즈 분석


이 블로그 시리즈는 요약 동시 프로그래밍을 기록하는 과정을 배우는 것입니다. 내가 쉽게 액세스 할 수 있도록 함께 카탈로그 페이스트 (포털)를 넣을 수 있도록 시간에 의해 쓰여진 더 많은 기사로, 상대적으로 느슨합니다.

동시 프로그래밍 시리즈 블로그 포털


에서 java.util.concurrent.atomic원자의 네 가지 유형의 다음과 같은 일반 :

  • AtomicBoolean는 : 기본 부울 데이터 유형의 원자 갱신 조작을 제공한다.
  • AtomicInteger는 :베이스 데이터 유형 INT 원자 갱신 조작을 제공한다.
  • AtomicLong : 긴베이스 데이터 유형의 원자 갱신 조작을 제공한다.
  • AtomicReference : 이것은 일반적인 클래스는 참조 타입의 원자 갱신 조작을 제공하는 것입니다.

관련 동작 종류의 배열은 :

  • AtomicLongArray : 제공 원자 업데이트 동작 INT [] 배열 요소.
  • AtomicIntegerArray 롱 [] 배열 요소 원자 갱신 조작을 제공한다.
  • 의 AtomicReferenceArray : 참조 형 어레이 요소의 [] 원자 갱신 조작을 제공한다.

거의 위의 원자 작업 클래스의 원칙의 실현으로, 우리가 선택하는 AtomicInteger분석.

코드 분석

생성자

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

    //Unsafe类提供底层的CAS机制 
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    //valueOffset是value值的内存地址值偏移值,这个值的作用是获取value在主内存中的值
    private static final long valueOffset;
    //类加载的时候获取valueOffset的值
    static {
        try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }

    //AtomicInteger具体的值存放在这个变量中,
    //这个变量使用volatile修饰,具有可见性
    private volatile int value;
    
    public AtomicInteger(int initialValue) {
        value = initialValue;
    }

    //默认为0
    public AtomicInteger() {
    }
}

get 및 set 메소드 분석

//value使用volatile修饰,每次能拿到最新值
public final int get() {
    return value;
}

//value使用volatile修饰,赋值操作具有原子性,是线程安全的
public final void set(int newValue) {
    value = newValue;
}

//这个方法可能比较令人疑惑,我查了下unsafe的putOrderedInt方法,如下

/**  Sets the value of the integer field at the specified offset in the
  * supplied object to the given value. This is an ordered or lazy
  * version of <code>putIntVolatile(Object,long,int)</code>, which
  * doesn't guarantee the immediate visibility of the change to other
  * threads. It is only really useful where the integer field is
  * <code>volatile</code>, and is thus expected to change unexpectedly.
  */
上面的意思大致是:putOrderedInt方法不保证可见性,只有在变量是volatile修饰时才有用,
我们这边的value变量就是用volatile修饰的,所以我认为AtomicInteger的`set`方法和`lazySet`方法
功能是一致的。
public final void lazySet(int newValue) {
    unsafe.putOrderedInt(this, valueOffset, newValue);
}

//将value设置成给定值,并返回旧值
public final int getAndSet(int newValue) {
    return unsafe.getAndSetInt(this, valueOffset, newValue);
}
//使用CAS机制更新
public final boolean compareAndSet(int expect, int update) {
    return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
//使用CAS机制更新
public final boolean weakCompareAndSet(int expect, int update) {
    return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
//CAS加1,并且返回原始值
public final int getAndIncrement() {
    return unsafe.getAndAddInt(this, valueOffset, 1);
}
//CAS减1,并且返回原始值
public final int getAndDecrement() {
    return unsafe.getAndAddInt(this, valueOffset, -1);
}
//CAS加减delta值,并且返回原始值
public final int getAndAdd(int delta) {
    return unsafe.getAndAddInt(this, valueOffset, delta);
}
//CAS加1,并且返回最新值
public final int incrementAndGet() {
    return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
//CAS减1,并且返回最新值
public final int decrementAndGet() {
    return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
}
//CAS加减delta值,并且返回最新值
public final int addAndGet(int delta) {
    return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
}

정책 업데이트

여기에 몇 가지 방법이 내가 매우 유용하지 않고, 구별이 통과되지 값을 업데이트됩니다 위, 그러나으로 생각 개인적으로 있습니다 IntUnaryOperatorIntBinaryOperator인터페이스를 세었다.

public final int getAndUpdate(IntUnaryOperator updateFunction) {
    int prev, next;
    do {
        prev = get();
        next = updateFunction.applyAsInt(prev);
    } while (!compareAndSet(prev, next));
    return prev;
}

public final int updateAndGet(IntUnaryOperator updateFunction) {
    int prev, next;
    do {
        prev = get();
        next = updateFunction.applyAsInt(prev);
    } while (!compareAndSet(prev, next));
    return next;
}

public final int getAndAccumulate(int x, IntBinaryOperator accumulatorFunction) {
    int prev, next;
    do {
        prev = get();
        next = accumulatorFunction.applyAsInt(prev, x);
    } while (!compareAndSet(prev, next));
    return prev;
}

 public final int accumulateAndGet(int x,IntBinaryOperator accumulatorFunction) {
    int prev, next;
    do {
        prev = get();
        next = accumulatorFunction.applyAsInt(prev, x);
    } while (!compareAndSet(prev, next));
    return next;
}

간단한 요약

원 자성을 보장하기 위해 CAS를 사용하여 가시성을 보장하는 휘발성 사용하고, 궁극적으로 보증 스레드 안전 변수 작업을 공유 : 전반적으로, AtomicBoolean, AtomicInteger, AtomicLong 및 AtomicReference 원리는 간단하다.

AtomicLongArray, 최종 메커니즘과 약간 다른 구현 원리 AtomicIntArray와의 AtomicReferenceArray는 공유 변수의 CAS의 스레드 안전한 작동을 구현하는 데 사용되는 메커니즘입니다. 그리고 관심있는 학생들은 상대적으로 간단하고, 자신을 분석 할 수 있습니다.

추천

출처www.cnblogs.com/54chensongxia/p/12161719.html