从三种单例模式的比较中了解volatile的真相
作者:互联网
本想吟诗一首,奈何才疏学浅。
吼吼得了
/**
* 加锁懒汉式单例模式
* 牺牲了性能(初始化后,仍会发生线程阻塞问题),保证了并发安全
*/
class SingleInstance2 {
private static SingleInstance2 singleInstance2;
public static synchronized SingleInstance2 getSingleInstance2(){
if (singleInstance2 == null) {
singleInstance2 = new SingleInstance2();
}
return singleInstance2;
}
} /**
* 饿汉式,既能保证并发安全,也能保证性能
* 缺点:类加载时就初始化,浪费内存
*/
class SingleInstance3 {
private static final SingleInstance3 singleInstance3 = new SingleInstance3();
public static SingleInstance3 getSingleInstance3() {
return singleInstance3;
}
} volatile/单例模式 学习笔记
/**
* 双重检查锁机制,兼顾性能与安全,初始化之后,不会发生线程阻塞
* Java指令执行的过程:1.将变量从主存复制到线程的工作内存中;2.然后进行读操作;3.有赋值指令时进行赋值操作;4.将结果写入主存中;
* 以上4步都是原子性的,但组合到一起,多线程操作时不能保证整体原子性,这也就是线程并发安全问题的原因。
* 其中volatile修饰词作用:
* 1.某一线程对volatile修饰的变量进行修改后,会强制将结果写入主存,并使其它线程缓存行失效(失效后,读操作不能从工作内存中直接读取,从步骤1开始),
* 即保证3和4指令执行过程的整体原子性,并通知其它线程。
* 2.禁止指令重排(代码的编写顺序和指令执行的顺序不一致),一定程度上保证了有序性。
* @author: dreamMaker
**/
public class SingleInstance {
private static volatile SingleInstance singleInstance;
public static SingleInstance getSingleInstance(){
//非空则跳过,因为只有首次初始化才有安全问题,保证了初始化之后,线程不会阻塞,提高了性能
if (singleInstance == null) {
synchronized(SingleInstance.class){
//voliatile能保证可见性,但不能保证原子性,加锁保证线程并发情况下,也只有一个实例
if (singleInstance == null) {
singleInstance = new SingleInstance();
}
}
}
return singleInstance;
}
} 可能会用双重所机制为什么要加volatile的疑问,提示:volatile会使其它线程的缓存行失效,读操作需要从重新存中去取。
/**
* 加锁懒汉式单例模式
* 牺牲了性能(初始化后,仍会发生线程阻塞问题),保证了并发安全
*/
class SingleInstance2 {
private static SingleInstance2 singleInstance2;
public static synchronized SingleInstance2 getSingleInstance2(){
if (singleInstance2 == null) {
singleInstance2 = new SingleInstance2();
}
return singleInstance2;
}
} /**
* 饿汉式,既能保证并发安全,也能保证性能
* 缺点:类加载时就初始化,浪费内存
*/
class SingleInstance3 {
private static final SingleInstance3 singleInstance3 = new SingleInstance3();
public static SingleInstance3 getSingleInstance3() {
return singleInstance3;
}
} volatile/单例模式 学习笔记
/**
* 双重检查锁机制,兼顾性能与安全,初始化之后,不会发生线程阻塞
* Java指令执行的过程:1.将变量从主存复制到线程的工作内存中;2.然后进行读操作;3.有赋值指令时进行赋值操作;4.将结果写入主存中;
* 以上4步都是原子性的,但组合到一起,多线程操作时不能保证整体原子性,这也就是线程并发安全问题的原因。
* 其中volatile修饰词作用:
* 1.某一线程对volatile修饰的变量进行修改后,会强制将结果写入主存,并使其它线程缓存行失效(失效后,读操作不能从工作内存中直接读取,从步骤1开始),
* 即保证3和4指令执行过程的整体原子性,并通知其它线程。
* 2.禁止指令重排(代码的编写顺序和指令执行的顺序不一致),一定程度上保证了有序性。
* @author: dreamMaker
**/
public class SingleInstance {
private static volatile SingleInstance singleInstance;
public static SingleInstance getSingleInstance(){
//非空则跳过,因为只有首次初始化才有安全问题,保证了初始化之后,线程不会阻塞,提高了性能
if (singleInstance == null) {
synchronized(SingleInstance.class){
//voliatile能保证可见性,但不能保证原子性,加锁保证线程并发情况下,也只有一个实例
if (singleInstance == null) {
singleInstance = new SingleInstance();
}
}
}
return singleInstance;
}
} 可能会用双重所机制为什么要加volatile的疑问,提示:volatile会使其它线程的缓存行失效,读操作需要从重新存中去取。
标签:volatile,真相,保证,SingleInstance,线程,单例,static,singleInstance 来源: https://www.cnblogs.com/yi-ma-dang-xian/p/10696858.html