이 블로그 시리즈는 요약 동시 프로그래밍을 기록하는 과정을 배우는 것입니다. 내가 쉽게 액세스 할 수 있도록 함께 카탈로그 페이스트 (포털)를 넣을 수 있도록 시간에 의해 쓰여진 더 많은 기사로, 상대적으로 느슨합니다.
에서 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;
}
정책 업데이트
여기에 몇 가지 방법이 내가 매우 유용하지 않고, 구별이 통과되지 값을 업데이트됩니다 위, 그러나으로 생각 개인적으로 있습니다 IntUnaryOperator
및 IntBinaryOperator
인터페이스를 세었다.
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의 스레드 안전한 작동을 구현하는 데 사용되는 메커니즘입니다. 그리고 관심있는 학생들은 상대적으로 간단하고, 자신을 분석 할 수 있습니다.