是乐观锁和原子类的底层原理
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.自旋问题长