是乐观锁和原子类的底层原理
1.大纲
什么是cas
代码演示
应用场景
一:CAS
1.说明
CAS:Compare and Swap,即比较再交换。
jdk5增加了并发包java.util.concurrent.*,其下面的类使用CAS算法实现了区别于synchronouse同步锁的一种乐观锁。JDK 5之前Java语言是靠synchronized关键字保证同步的,这是一种独占锁,也是是悲观锁。
https://www.cnblogs.com/juncaoit/p/12386737.html
2.cpu的特殊指令
cpu保证原子性
package com.jun.juc.cas; /** * CAS等价代码 */ public class SimulatedCas { private volatile int value; public synchronized int compareAndSwap(int expectdValue, int newValue){ int oldValue = value; if(oldValue == expectdValue){ value = newValue; } return oldValue; } }
二:代码演示
1.演示
package com.jun.juc.cas; import java.util.concurrent.Executors; /** * CAS演示 */ public class Competition implements Runnable{ private volatile int value; public synchronized int compareAndSwap(int expectdValue, int newValue){ int oldValue = value; if(oldValue == expectdValue){ value = newValue; } return oldValue; } @Override public void run() { compareAndSwap(0,1); } public static void main(String[] args) throws Exception{ Competition competition = new Competition(); competition.value = 0; Thread t1 = new Thread(competition); Thread t2 = new Thread(competition); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(competition.value); } }
效果:
Connected to the target VM, address: '127.0.0.1:62710', transport: 'socket' 1 Disconnected from the target VM, address: '127.0.0.1:62710', transport: 'socket' Process finished with exit code 0
三:应用场景
1.举例
乐观锁
并发容器
原子类
2.并发容器
ConcurrentHashmap
四:原子类什么应用CAS的
1.说明
AtomicInteger架在Unsafe工具,用来直接操作内存数据
用Unsafe来实现底层操作
用volatile修饰value字段,保证可见性
getAndAddInt方法分析
2.代码
// setup to use Unsafe.compareAndSwapInt for updates private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final long valueOffset; static { try { valueOffset = unsafe.objectFieldOffset (AtomicInteger.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } } private volatile int value;
/** * Atomically adds the given value to the current value. * * @param delta the value to add * @return the previous value */ public final int getAndAdd(int delta) { return unsafe.getAndAddInt(this, valueOffset, delta); }
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; }
public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
3.Unsafe类
是CAS核心类
java无法直接访问底层操作系统,是通过本地native方法来进行访问。jvm还是提供了一个后门,这个类提供了硬件级别的原子操作
valueOff表示的是变量值在内存中的偏移地址,因为unsafe就是根据内存偏移地址获取数据的原值的,这样我们就可以通过unsafe实现cas了
五:不好的问题
1.ABA问题
解决的方式,类似数据库那种,添加版本号
2.自旋问题长