博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java 单例模式的线程安全实现
阅读量:6876 次
发布时间:2019-06-26

本文共 1600 字,大约阅读时间需要 5 分钟。

  hot3.png

先看一下一般的实现方式

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. m_instance=new lazySingleton();语句编译之后其实是包含两条指令,new lazySingleton()指令和给m_instance赋值。由于编译时或CPU执行时指令重排序,可能存在先给m_instance赋值,后初始化对象的情况。这时,就出现一种情况,m_instance值不为null,但是m_instance对象还没有实例化完成。
  2. 当线程A执行到a处时,m_instance值不为null,但是m_instance对象还没有实例化完成。线程B由于m_instance值不为null,从b出到c处返回m_instance对象。
  3. 当线程B调用m_instance的方法时,将引发对象尚未初始化错误。

解决:针对引发问题的主要原因1和2,分别提出解决的办法。

  • 方法一:private static volatile lazySingleton m_instance=null;在m_instance前添加volatile 关键字,提醒编译器和运行时环境,在volatile变量上的操作不能与其它操作重排序,从而避免后续问题产生。

  • 方法二:在getInstance方法前添加synchronized 同步锁,保证同时只会有一个线程getInstance方法,也就保证了在A线程返回m_instance之前,其他线程都是阻塞状态。也就不会出现m_instance值不为null,但是m_instance对象还没有实例化完成的情况。

除了以上两种方法,还有一种简单安全还可靠的方法,那就是依赖JVM的静态类的静态属性实现单例模式。如下

public class Singleton {   static class SingletonHolder {     static Singleton instance = new Singleton();   }       public static Singleton getInstance(){     return SingletonHolder.instance;   } }

此种写法利用了类加载器的加载原理,每个类只会被加载一次,这样单例对象在其内部静态类被加载的时候生成,而且此过程是线程安全的。

转载于:https://my.oschina.net/u/1774673/blog/811197

你可能感兴趣的文章
算法 表达式求值
查看>>
用Qt写了一个qq客户端,采用webqq协议,发出来和大家分享一下---大神请无视
查看>>
ResulsetHandler九个实现类
查看>>
python 函数
查看>>
找出在使用临时表空间的SQL
查看>>
MapReduce 学习(一)
查看>>
专访李智慧:架构是最高层次的规划和难以改变的决定
查看>>
HTML5 入门基础
查看>>
Laravel 中的 Many-To-Many
查看>>
Codeforces 371C Hamburgers(二分基础题)
查看>>
django 自定义tag和filter
查看>>
FileWriter写数据路径问题及关闭和刷新方法的区别
查看>>
Page Layout里的javascript (jquery)不执行
查看>>
JS中的发布订阅模式
查看>>
解析JMeter的JTL文件
查看>>
1-N中1出现的次数
查看>>
springmvc自定义视图
查看>>
windows driver 映射大文件
查看>>
《R语言实战》读书笔记--第三章 图形初阶(一)
查看>>
MFC串口的编程 mscomm控件与SerialPort类
查看>>