CAS(Compare And Swap),即比较并交换。是解决多线程并行情况下使用锁造成性能损耗的一种机制,CAS操作包含三个操作数——内存位置(V)、预期原值(A)和新值(B)。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作。无论哪种情况,它都会在CAS指令之前返回该位置的值。CAS有效地说明了“我认为位置V应该包含值A;如果包含该值,则将B放到这个位置;否则,不要更改该位置,只告诉我这个位置现在的值即可。
CAS典型应用
java.util.concurrent.atomic 包下的类大多是使用CAS操作来实现的(eg. AtomicInteger.java,AtomicBoolean,AtomicLong)。下面以 AtomicInteger.java 的部分实现来大致讲解下这些原子类的实现。
1 public class AtomicInteger extends Number implements java.io.Serializable { 2 private static final long serialVersionUID = 6214790243416807050L; 3 4 // setup to use Unsafe.compareAndSwapInt for updates 5 private static final Unsafe unsafe = Unsafe.getUnsafe(); 6 7 private volatile int value;// 初始int大小 8 // 省略了部分代码... 9 10 // 带参数构造函数,可设置初始int大小 11 public AtomicInteger(int initialValue) { 12 value = initialValue; 13 } 14 // 不带参数构造函数,初始int大小为0 15 public AtomicInteger() { 16 } 17 18 // 获取当前值 19 public final int get() { 20 return value; 21 } 22 23 // 设置值为 newValue 24 public final void set(int newValue) { 25 value = newValue; 26 } 27 28 //返回旧值,并设置新值为 newValue 29 public final int getAndSet(int newValue) { 30 /** 31 * 这里使用for循环不断通过CAS操作来设置新值 32 * CAS实现和加锁实现的关系有点类似乐观锁和悲观锁的关系 33 * */ 34 for (;;) { 35 int current = get(); 36 if (compareAndSet(current, newValue)) 37 return current; 38 } 39 } 40 41 // 原子的设置新值为update, expect为期望的当前的值 42 public final boolean compareAndSet(int expect, int update) { 43 return unsafe.compareAndSwapInt(this, valueOffset, expect, update); 44 } 45 46 // 获取当前值current,并设置新值为current+1 47 public final int getAndIncrement() { 48 for (;;) { 49 int current = get(); 50 int next = current + 1; 51 if (compareAndSet(current, next)) 52 return current; 53 } 54 } 55 56 // 此处省略部分代码,余下的代码大致实现原理都是类似的 57 }