1、无锁类的原理详解
1.1 CAS
CAS算法:含3个参数CAS(V,E,N)。V表示要更新的变量,E表示预期值,N表示新值。
仅当V值等于E值时,才会将V的值设为N。如果V值和E值不同,则说明已经有其他线程做了更新,则当前线程什么
都不做。最后,CAS返回当前V的真实值。
CAS操作是抱着乐观的态度进行的,它总是认为自己可以成功完成操作。
当多个线程同时使用CAS操作一个变量时,只有一个会胜出并更新。失败的线程不会被挂起,仅是被告知失败,允许再次尝试,
当然也允许失败的线程放弃操作。基于这样的原理,CAS操作即时没有锁,也可以发现其他线程对当前线程的干扰,并进行恰当的处理。
1.2 CPU指令
底层使用CPU指令实现
2、无锁类的使用
2.1 AtomicInteger
Number
public final int get() //取得当前值
public final void set(int newValue) //设置当前值
public final int getAndSet(int newValue) //设置新值,并返回旧值
public final boolean compareAndSet(int expect, int u)
//如果当前值为expect,则设置为u
public final int getAndIncrement() //当前值加1,返回旧值
public final int getAndDecrement() //当前值减1,返回旧值
public final int getAndAdd(int delta) //当前值增加delta,返回旧值
public final int incrementAndGet() //当前值加1,返回新值
public final int decrementAndGet() //当前值减1,返回新值
public final int addAndGet(int delta) //当前值增加delta,返回新值
2.2 Unsafe
非安全的操作,
比如:根据偏移量设置值;
park();
底层的CAS操作;
非公开API,在不同版本的JDK中,可能有较大差异;
主要接口:
//获得给定对象偏移量上的int值
public native int getInt(Object o, long offset);
//设置给定对象偏移量上的int值
public native void putInt(Object o, long offset, int x);
//获得字段在对象中的偏移量
public native long objectFieldOffset(Field f);
//设置给定对象的int值,使用volatile语义
public native void putIntVolatile(Object o, long offset, int x);
//获得给定对象对象的int值,使用volatile语义
public native int getIntVolatile(Object o, long offset);
//和putIntVolatile()一样,但是它要求被操作字段就是volatile类型的
public native void putOrderedInt(Object o, long offset, int x);
2.3 AtomicReference
对引用进行修改;是一个模板类,抽象化了数据类型;
主要接口:
get()
set(V)
compareAndSet()
getAndSet(V)
2.4 AtomicStampedReference
可解决ABA问题 (金融交易,数字敏感的问题);
主要接口:
//比较设置 参数依次为:期望值写入新值期望时间戳 新时间戳
public boolean compareAndSet(V expectedReference,V newReference,int expectedStamp,int newStamp)
//获得当前对象引用
public V getReference()
//获得当前时间戳
public int getStamp()
//设置当前对象引用和时间戳
public void set(V newReference, int newStamp)
2.5 AtomicIntegerArray
支持无锁的数组;
比AtomicInteger多传入一个下标,维护数组操作;
2.6 AtomicIntegerFieldUpdater
让普通变量也享受原子操作;
尽量少的修改已有的变量;
3、无锁算法详解
3.1 无锁的Vector实现
LockFreeVector:
相对于有所的Vector,相率低,使用synchronized加锁;
LockFreeVector内部使用AtomicReferenceArray 实现,多个 <AtomicReferenceArray >buckets 实现;