volatile
关键字
-
特点:
-
可见性
-
有序性:禁止指令重排
-
但类似于volatile++这种复合操作不具有原子性
-
-
内存语义:
- 当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量值立即刷新回主内存中
- 当读一个volatile变量时,JMM会把该线程对应的本地内存设置为无效,重新回到主内存中读取最新共享变量的值
所以volatile的写内存语义是直接刷新到主内存中,读的内存语义是直接从主内存中读取
单例模式
//https://www.cnblogs.com/luonote/p/10347427.html
//饿汉式:
class Singleton {
// 1.私有化构造器
private Singleton() {
}
// 2.内部提供一个当前类的实例
// 4.此实例也必须静态化
private static final Singleton single = new Singleton();
//饿汉式单例在new对象时为什么不需要加volatile?
//https://www.zhihu.com/question/453028971/answer/2112832011
// 3.提供公共的静态的方法,返回当前类的对象
public static Singleton getInstance() {
return single;
}
}
//懒汉式:
class Singleton {
// 1.私有化构造器
private Singleton() {
}
// 2.内部提供一个当前类的实例
// 4.此实例也必须静态化
private volatile static Singleton single = null;//volatile防止指令重排序
// 3.提供公共的静态的方法,返回当前类的对象
public static Singleton getInstance() {
if(instance == null){//效率更高
synchronized(Singleton.class){//同步锁
if(instance == null){
instance = new Singleton();//初始化和赋值可能重排序
}
}
}
return instance;
}
}
//在方法上加同步锁,效率低
class Singleton {
private Singleton() {
}
private static Singleton instance = null;
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
//使用InstanceHolder
class Singleton {
private Singleton() {
}
private static final class InstanceHolder {
static final Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return InstanceHolder.instance;
}
}
CAS和原子类
public class AtomicClassTest {
public static void main(String[] args) throws InterruptedException {
IncreaseInteger val = new IncreaseInteger();
System.out.println(val.get());
new Thread(() -> {
for (int i = 0; i < 10000; i++) {
val.increase();
}
}).start();
new Thread(() -> {
for (int i = 0; i < 10000; i++) {
val.increase();
}
}).start();
Thread.sleep(1000);
System.out.println(val.get());
}
}
//原子类 ✓
class IncreaseInteger{
private AtomicInteger value = new AtomicInteger(1);
public void increase(){
value.incrementAndGet();
}
public Integer get(){
return value.get();
}
}
//volatile + 锁 ✓
class IncreaseInteger{
private volatile Integer value = 1;//保证可见性
public synchronized void increase(){//保证原子性
value++;
}
public Integer get(){
return value;
}
}
//并发会出现问题
class IncreaseInteger {
private Integer value = 1;
public void increase() {
value++;
}
public Integer get() {
return value;
}
}