Java 单例模式学习理解

175 阅读2分钟

正常的单例模式如下所示:

public class SingleTon {
    private volatile static SingleTon sInstance;

    private SingleTon() {
    }

    public static SingleTon getInstance() {
        if (sInstance == null) {
            synchronized (SingleTon.class) {
                if (sInstance == null) {
                    sInstance =  new SingleTon();
                }
            }
        }
        return sInstance;
    }
}

关于这段代码,有些问题和理解:

1、私有化构造函数,保证了其他类调用的时候不能通过这种方式初始化获得对象。
2、提供一个公共的静态方法获取实例对象。此时为何要进行两次判空操作呢?
a、第一次判空操作是为了避免每次都执行synchronized同步锁的操作,synchronized是很消耗性能的操作,
如果第一次不为空,则不用去执行同步锁操作。
b、synchronized可以保证每个时刻只有一个线程执行同步代码,准确的说是保证线程间的有序性操作。
c、第二次判空则是防止多个类都调用该方法时,多次获取实例对象。如果已经实例化后,则此时不会再实例化对象。
3、synchronized方法里的SingleTon.class可以换成SingleTon.this吗?答案是不可以。
原因是synchronized同步块括号中的锁定对象是采用的一个无关的Object类实例,而不是采用this,
因为getInstance是一个静态方法,在它内部不能使用非静态的或者未实例的类对象
4、volatile 关键字
首先,sInstance =  new SingleTon();这句话做了哪些事情
a、给sInstance实例分配内存。
b、初始化SingleTon()成员变量。
c、将sInstance对象指向new Singleton()分配的内存空间,所以这个时候sInstance就不为null了。
此时问题出现了,如果按照abc顺序执行,则一切正常,但是JVM有指令重排序的优化,所以有可能会按
照acb的顺序执行,那这样就出现问题了。volatile就是防止重排序的,这样就能正常获取单例了。

关于单例的学习笔记,便于以后回顾