先看一下通常的实现方式安全
public class lazySingleton { private static lazySingleton m_instance=null; private lazySingleton() { // TODO Auto-generated constructor stub System.out.println("构造函数"); } public static lazySingleton getInstance(){ if(m_instance==null){//b synchronized (lazySingleton.class) { if(m_instance==null){ m_instance=new lazySingleton(); //a } } } return m_instance;//c } public void print(){ System.out.println("print"); } public static void main(String[] args) { // TODO Auto-generated method stub lazySingleton.getInstance().print(); } }
这种实现方式,在单线程模式下彻底没有问题。但在多线程模式下,则可能引起报错。 缘由以下:多线程
解决:针对引起问题的主要缘由1和2,分别提出解决的办法。函数
方法一:private static volatile lazySingleton m_instance=null;在m_instance前添加volatile 关键字,提醒编译器和运行时环境,在volatile变量上的操做不能与其它操做重排序,从而避免后续问题产生。线程
方法二:在getInstance方法前添加synchronized 同步锁,保证同时只会有一个线程getInstance方法,也就保证了在A线程返回m_instance以前,其余线程都是阻塞状态。也就不会出现m_instance值不为null,可是m_instance对象尚未实例化完成的状况。code
除了以上两种方法,还有一种简单安全还可靠的方法,那就是依赖JVM的静态类的静态属性实现单例模式。以下对象
public class Singleton { static class SingletonHolder { static Singleton instance = new Singleton(); } public static Singleton getInstance(){ return SingletonHolder.instance; } }
此种写法利用了类加载器的加载原理,每一个类只会被加载一次,这样单例对象在其内部静态类被加载的时候生成,并且此过程是线程安全的。排序