GYM3-无锁

CAS compare and swap

线程切换线程8w个时钟周期。对于竞争不激烈的情况,使用循环使用CAS开销更小。
无锁操作在并发比较少的情况下效率高,但不要迷恋无锁。
CAS是CPU指令级别的原子操作,一条指令完成比较赋值过程,不用担心并发问题。

AtomicInteger

AtomicInteger 部分源码

1
2
3
4
5
6
7
8
9
10
11
// setup to use Unsafe.compareAndSwapInt for updates
//只有bootstrap加载器加载的类才能获取Unsafe的实例,其他类只能用反射获取
private static final Unsafe unsafe = Unsafe.getUnsafe();
//valueOffset 代表需要更新的字段在对象中的偏移量,类似于c中的指针,获取需要更新字段的内存地址
private static final long valueOffset;
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}

Unsafe 部分源码

1
2
3
4
5
6
7
8
9
10
11
//valueOffset 代表需要更新的字段在对象中的偏移量,类似于c中的指针,获取需要更新字段的内存地址
public final native boolean compareAndSwapInt(Object var1,long valueOffset, expect, update);
//不断zi'x
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;
}

AtomicReference

  可以修饰任意类型的变量,是的变量操作变为院子操作
AtomicReference stringAtomicReference = new AtomicReference<>();

AtomicStampedReference

  与AtomicReference功能相似,不同点是AtomicStampedReference可以解决过程相关的情景。过程敏感的情景试用。
  假设一个活动只能给每个用户充值一次10元钱,用户可以消费。假设用户A充值以后立马消费10元,AtomicReference还会认为只消费了一次。
  

1
2
3
AtomicStampedReference<Integer> money = new AtomicStampedReference<>(0,0);
int stamp = money.getStamp();
money.compareAndSet(0,10,stamp,stamp+1);

AtomicStampedReference部分源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
private static class Pair<T> {
final T reference;
final int stamp;
private Pair(T reference, int stamp) {
this.reference = reference;
this.stamp = stamp;
}
static <T> Pair<T> of(T reference, int stamp) {
return new Pair<T>(reference, stamp);
}
}

private volatile Pair<V> pair;
//构造函数
public AtomicStampedReference(V initialRef, int initialStamp) {
pair = Pair.of(initialRef, initialStamp);
}

public boolean compareAndSet(V expectedReference, V newReference,
int expectedStamp, int newStamp) {
Pair<V> current = pair;
return expectedReference == current.reference &&
expectedStamp == current.stamp &&
((newReference == current.reference &&
newStamp == current.stamp) ||
casPair(current, Pair.of(newReference, newStamp)));
}
private boolean casPair(Pair<V> cmp, Pair<V> val) {
return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);
}

AtomicIntegerArray

原子操作的整数数组

1
2
3
AtomicIntegerArray array = new AtomicIntegerArray(10);
//下标为2的位置加一
array.getAndIncrement(2);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final int base = unsafe.arrayBaseOffset(int[].class);
private static final int shift;
private final int[] array;

static {
int scale = unsafe.arrayIndexScale(int[].class);
if ((scale & (scale - 1)) != 0)
throw new Error("data type scale not a power of two");
shift = 31 - Integer.numberOfLeadingZeros(scale);
}

private long checkedByteOffset(int i) {
if (i < 0 || i >= array.length)
throw new IndexOutOfBoundsException("index " + i);

return byteOffset(i);
}

private static long byteOffset(int i) {
return ((long) i << shift) + base;
}
public AtomicIntegerArray(int length) {
array = new int[length];
}
public AtomicIntegerArray(int[] array) {
// Visibility guaranteed by final field guarantees
this.array = array.clone();
}
public final int getAndIncrement(int i) {
return getAndAdd(i, 1);
}
public final int getAndAdd(int i, int delta) {
return unsafe.getAndAddInt(array, checkedByteOffset(i), delta);
}

AtomicIntegerFieldUpdater

AtomicIntegerFieldUpdater辅助一个类,用类似静态方法的方式,实现变量的原子操作。优点在于不必改变变量的类型,即可享受原子变量的好处。如果是已有代码修改,将会大大减少代码的修改量。

1
2
3
4
5
6
7
public static class Candidate{
int id = 0 ;
volatile int score = 0;
}
AtomicIntegerFieldUpdater<Candidate> scoreUpdater = AtomicIntegerFieldUpdater.newUpdater(Candidate.class, "score");
Candidate candidate = new Candidate();
scoreUpdater.incrementAndGet(candidate);

AtomicIntegerFieldUpdater部分源码

1
2
3
4
5
6
7
8
public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass,
String fieldName) {
Class<?> caller = Reflection.getCallerClass();
if (AtomicLong.VM_SUPPORTS_LONG_CAS)
return new CASUpdater<U>(tclass, fieldName, caller);
else
return new LockedUpdater<U>(tclass, fieldName, caller);
}

LockFreeVector

无锁数组,amino框架提供

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//第一桶的大小为8 
private static final int First_BUCKET_SIZE = 8;
//采用二维数组做扩展,每个一维数组的大小都不同 sizeOf(buke[i+1]) = sizeOf( buket[i]) *2
private final AtomicReferenceArray<AtomicReferenceArray<E>> buckets;
static class WriteDescriptor<E>{
public E odlV;
public E newV;
public AtomicReferenceArray<E> addr; //操作地址
public int addr_ind;//地址的index
public WriteDesciptor(AtomicReferenceArray<E> addr,int addr_ind, E oldV,E newV){
this.addr = addr;
this.addr_ind =addr_ind;
this.oldV = oldV;
this.newV = newV;
}
public void doIt(){
addr.compareAndSet()
}
public void push_back(E e){
Desciptor
}