正常的单例模式如下所示:
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就是防止重排序的,这样就能正常获取单例了。复制代码
关于单例的学习笔记,便于以后回顾