博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
对Java单例模式 volatile关键字作用的理解
阅读量:6195 次
发布时间:2019-06-21

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

  单例模式是程序设计中经常用到的,简单便捷的设计模式,也是很多程序猿对设计模式入门的第一节课。其中最经典的一种写法是:

class Singleton {    private volatile static Singleton instance;//volatile关键字防止指令重排    private Singleton(){}    public static Singleton getInstance() {        if ( instance == null ) { //一重判断            synchronized (Singleton.class) {//对Singleton.class上锁                if ( instance == null ) {//二重判断                    instance = new Singleton();                }            }        }        return instance;    }}

  其中有两个关键的地方:1,初始化instance实例的时候,采用两重判断对Singleton.class上锁。

             2,静态变量instance使用了volatile关键字进行修饰。

  第一个问题相对比较好理解  

if ( instance == null ) { //一重判断            synchronized (Singleton.class) {//对Singleton.class上锁                if ( instance == null ) {//二重判断                    instance = new Singleton();                }            }        }

  

  sychronized关键字锁住Singleton类而不是instance对象,是因为,此时instance为空,加sychronized没有意义。

第一重判断的意义在于:如果instance非空,就跳过了锁的步骤,减少加锁的资源开销。但是由于第一重判断在代码锁之外,如果不同线程同时访问到install==null,会先后阻塞执行代码锁内的内容。所以在代码锁内加第二重判断就很有必要了,避免第一个线程获取实例后,第二个线程获得资源锁又执行了一次instance的初始化,产生两个不同的实例。
  很多人不理解instance实例在声明时加volatile关键字的作用,或者是发现别人这么写了,自己也跟着这么写。对volatile关键字的解释,很多地方只是提了句“当要求使用volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,它可以防止指令重排”,这里不想对这句话进行展开解释,想详细了解可以参考文章
  https://www.cnblogs.com/shan1393/p/8999683.html
  https://www.cnblogs.com/xrq730/p/7048693.html

  instance = new Singleton()看上去只有一句话,但java的初始化成员变量包括内存分配、初始化、返回对象在堆上的引用等一系列操作。对于synchronized代码块内,一条语句完整执行是没有问题的。但如果发生了指令重排,先返回对象在堆上的引用,再进行初始化。对于另一个执行到一重判断的线程来说,由于instance已经指向了堆上的一段内存空间,那么instance就不为空,会将未完成初始化的对象返回给其他函数调用,引发一系列不安全隐患。加了volatile关键字,可以保证返回对象在对上的引用发生在初始化之后,避免了这种情况的发生。这就是单例模式下 instance加volatile关键字的作用。

转载于:https://www.cnblogs.com/acesui/p/9557501.html

你可能感兴趣的文章
Ubuntu 无法mount解决办法
查看>>
CSS一些最佳实践
查看>>
8.Kubernetes Service(服务)
查看>>
iOS开发库的族“.NET研究”谱介绍
查看>>
图解DevExpress RichEditControl富文本的使用,附源码及官方API
查看>>
BNU 34986 Football on Table
查看>>
三级联动---城市地区选择
查看>>
剖析 Laravel 计划任务--避免重复
查看>>
公司框架遇到的问题
查看>>
详解 Discuz 的 PHP经典加密解密函数 authcode
查看>>
Mysql XX 天之内
查看>>
AE创建气泡式的提示框(VB.Net和C#源码)
查看>>
Oracle如何删除表中重复记录
查看>>
nginx 是如何处理访问请求的
查看>>
wget参数用法详解
查看>>
安卓自学应用程序生命周期法
查看>>
【COCOS2D-X(1.X 2.X)】Json(cpp版)以及添加自定义字体库教程
查看>>
使用curl命令查看访问url的时间
查看>>
whois
查看>>
python添加环境变量
查看>>