从三种单例模式的比较中了解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会使其它线程的缓存行失效,读操作需要从重新存中去取。
上一篇:Android一个MediaPlayer实例 – 单例


下一篇:java-并发编程-多线程设计模式-单例设计模式的七种写法