1.双重检验锁(dcl)饿汉单例模式
package program.singleton;
//饿汉式
public class Lsingleton {
//声明volatile
private volatile static Lsingleton instance;
private Lsingleton(){ }
public static Lsingleton getInstance(){
if(instance==null){
synchronized (Lsingleton.class){
if(instance==null){
instance=new Lsingleton();
}
}
}
return instance;
}
}
为什么需要加上volatile关键字修饰变量呢?
2.CAS是什么?
CAS→Unsafe→CAS底层→ABA→原子引用更新→规避ABA
Compare And Set(或者说Compare And Swap,根据它调用的native method说),从内存某一时刻取出数据并在当下时刻比较并替换,是一条cpu执行原语。 CAS+自旋锁
使用Unsafe类与自旋锁,根据内存地址偏移量获取数据。
线程从主内存中读取值,保存在各自的私有线程工作内存中,
修改此值并写入主内存中,
CAS会从主内存读取并且判断与给定初值是否相等,
如果是相等,则修改写入主内存,否则继续获取主内存值直到修改成功。
3.CAS与Synchronized区别
Synchronized:可以保证数据一致性,
- 由于在线程间加锁,降低了系统的并发性。
CAS:可以保证数据一致性,不加锁并发性加强,
- 需要多次循环(自旋锁)开销大,
- 只能保证一个共享变量的原子操作,
- 引出"ABA"问题
4."ABA"问题以及解决方法
CAS(Compare And Set)发生时,会从内存某一时刻取出数据并在当下时刻比较并替换,那么再这个时间差类会导致数据发生变化,也就是“ABA”问题。
概念
简单的来说,发生CAS时,因为需要从内存中读取值,比较并替换,在这个时间差中,会使得原本为A的数据由A->B->A,虽然程序依旧可以正常执行,但是不能说他是正常处理的。(狸猫换太子)
解决方法
原子引用+版本号(时间戳,类似于乐观锁)
AtomicStampReference(初始值,更新值,初始版本号,修改版本号)