多线程与高并发(2)
volatile
- 保证线程可见性
- 禁止指令重排序
DCL单例是否需要加volatile
package com.liyuanchen.designPattern;
/**
* 双重检查线程安全单例模式需要加上volatile禁止指令重排序才能使对象中的成员变量值绝对正确
*/
public class DCLTest {
public static volatile DCLTest INSTANCE;
private DCLTest(){
}
public static DCLTest getInstance(){
if (null == INSTANCE) {
synchronized (DCLTest.class) {
if (null == INSTANCE) {
INSTANCE = new DCLTest();
}
}
}
return INSTANCE;
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(() -> {
System.out.println(DCLTest.getInstance().hashCode());
}).start();
}
}
}
volatile并不能代替synchronized,因为它不能保证多线程对变量的非原子操作数据正确。
CAS(Compare And Set/Swap 乐观锁 无锁优化)
cas是一种乐观锁机制,它有三个参数,一个当前内存值、旧的预期值、即将更新的值,仅当预期值与当前值相同时,将内存值修改为即将更新的值病返回true,否则什么都不做,返回false。
java中的Atomic原子类就是以CAS方式实现,如果更新不成功,则以自旋的方式继续进行操作。
CAS的ABA问题
旧的预期值在对比时与当前内存值是一致的,但是在比较之前与获取旧的预期值这段时间中发生过改变并且改回了原来的值,这时候就是CAS的ABA问题。
通常在CAS实现中加一个version字段来记录版本号来避免ABA问题。Java中AtomicStampedReference实现了这个处理方式。