单例模式到Java内存模型

先说单例模式:

经典的单例模式实现:

饿汉式:

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

懒汉式:

public class Singleton {private static Singleton instance = null;synchronized public static Singleton getInstance(){if(instance ==null){instance = new Singleton();}return instance;}
}

这两种都是可以安全运行在多线程下的。但是每一个都有点缺点,对于第一种如果这个单例的初始化需要很多内存和时间,我们希望用到时在初始化,没有用到就不初始化。对于第二种我们,其实只需要在第一次初始化时需要避免线程冲突,其他时候都可以直接返回的,而第二种的实现则变成了完全的串行(因为每一个操作都需要获得对象锁),非常大的降低了并发度。

我们尝试以下改进:

一个好的方式是DCL(double-checked locking),这种方式的实现如下:

public class Singleton {private static Singleton instance = null;public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null)instance = new Singleton();}}return instance;}
}

这样看起来是完美的解决方案,确实DCL是一个很好的解决思想,在C下其能很好的运行,但在Java下就会有问题了。这全怪Java的JMM(Java内存模型)。

在执行到instance = new Singleton()这里时,由于Java内存的“无序写入”,

可能的执行顺序是这样的:

mem = allocate();             //Allocate memory for Singleton object.
 instance = mem;               //Note that instance is now non-null, but has not been initialized.
 ctorSingleton(instance);      //Invoke constructor for Singleton passinginstance.

即为instance分配内存,标记instance不为空,初始化instance。

这样会导致,一个线程刚标记完,还没有初始化赋值给instance,就释放了锁,然后另一个线程进入锁,判断不为空,释放锁,返回instance,这时显然是错的。这里出现这中错误的原因是instance = new instance();并没有真正的执行完,就释放了锁,我实在不能理解这样设计的原因,但很好的是在JDK1.5之后,已不存在这种问题了DCL这个可以很好的运行。但我们还是有必要继续讨论JDK1.5之前如何实现的。

可以在instance返回之前加一个步奏,确定其确实初始化了。

public class Singleton {private static Singleton instance = null;public static Singleton getInstance() {if (instance == null) {Singleton temp = instance;synchronized (Singleton.class) {if (temp == null)instance = new Singleton();}instance = temp;}return instance;}
}

这样就很好的解决这个问题了。但是代码量和可阅读性已经陡然上升了,那么有没有更好的方法呢?是有的,利用类加载机制来实现,延迟初始化。

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

这里补充一点类加载的知识,类加载分为一个步骤,加载->验证->准备->解析->初始化->使用->卸载。

Java中对何时初始化一个类有严格的说明,这里涉及到的一个规则是当类的静态域,或静态方法被引用的时候,必须对声明这个静态域或方法的类进行初始化。至于说明时候对类进行加载,这个有两种形式:饿加载(只要有其他类引用了它就加载),懒加载(初始化的时候才加载)。具体JVM对这点的实现不同。

所以当懒汉式能保证用到的时候才进行初始化,而饿汉试则是在加载时就初始化了。

 

转载于:https://www.cnblogs.com/chaiwentao/p/4959648.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/459545.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

html 转word c#,c#操作word类,进行html和word文档的互相转换

#region 把Word文档装化为Html文件/** ///把Word文档装化为Html文件/// /// 要转换的Word文档public static void WordToHtml( stringstrFileName ){string saveFileName strFileName DateTime.Now.ToString( "yyyy-MM-dd-HH-mm-ss" ) ".html";WordToHt…

poj 1276 多重背包

735 3 4 125 6 5 3 350    //735的最大额&#xff0c;3种&#xff0c;4个125,6个5,3个350 633 4 500 30 6 100 1 5 0 1 735 0 0 3 10 100 10 50 10 10 735 630 0 0 1 #include<cstdio>2 #include<iostream>3 #include<algorithm>4 #include<…

《深入剖析Tomcat》阅读(三)

这里要介绍下Tomcat的一个重要设计方法&#xff0c;Catalina设计方式。 Servlet容器是一个复杂系统&#xff0c;但是&#xff0c;它有三个基本任务&#xff0c;对每个请求&#xff0c;servlet容器会为其完成以下三个操作&#xff1a; 1.创建一个Request对象&#xff0c;用可能会…

美图秀秀计算机教程,美图秀秀怎么抠图 美图秀秀抠图详细教程

怎么抠图&#xff1f;这是很多人在进行图片处理过程中经常处理的问题。对于那些专业人士来说&#xff0c;他们大多数用的是PS软件。但是对于绝大多数没有接触过PS的小白来说&#xff0c;怎么抠图成为了一大难题。其实&#xff0c;用过美图秀秀这款软件的朋友来说&#xff0c;它…

磁盘及文件系统的管理

分区是为了创建文件系统MBR&#xff1a;创建分区后&#xff0c;为了能够快速的存取文件就有了文件系统inode&#xff1a;中存储了文件属组&#xff0c;等与文件数据没有关系的文件属性信息&#xff0c;但是没有文件名每次访问某个目录的文件时是会进行缓存的&#xff0c;在一定…

今天升级win10.vs调试程序各种崩溃

今天升级win10.vs调试程序各种崩溃。感觉代码没问题。崩溃时有时没有。不知道是win10的问题&#xff0c;好真是我的代码问题。 问题1&#xff1a; 尝试读取或写入受保护的内存。这通常指示其他内存已损坏 不过。当我写这个文章时。想要重现一下。却又不出现了。 转载于:https:/…

计算机控制分离性原理是什么,(第12讲)状态观测器和分离原理.ppt

《(第12讲)状态观测器和分离原理.ppt》由会员分享&#xff0c;可在线阅读&#xff0c;更多相关《(第12讲)状态观测器和分离原理.ppt(26页珍藏版)》请在人人文库网上搜索。1、现代控制理论,(第10讲 2007年12月) 状态观测器 带观测器的闭环系统 分离原理 自动化教研室 谭功全,状态…

Cocos2d-x 3.8.1+Cocos Studio 2.3.2捉虫记之控制场景文件中的骨骼动画

Cocos2d-x 3.8.1Cocos Studio 2.3.2捉虫记之控制场景文件中的骨骼动画引子这段时间一直努力在把早期版本的拇指接龙游戏&#xff08;Cocos2d-x 2.2.3CocoStudio 1.4.0.1&#xff09;升级到当前相对稳定的高大上环境——Cocos2d-x 3.8.1Cocos Studio 2.3.2。行程中遇到不少麻烦&…

用JSmooth制作java jar文件的可运行exe文件教程【图文】

这是我之前在个人博客3yj上面写的一篇文章&#xff0c;如今转载过来&#xff0c;原文地址 &#xff08;这不是广告哦&#xff09; 几年前&#xff0c;刚接触java的是&#xff0c;就想用一些方法把自己的劳动果实保护起来&#xff0c;曾经也用过非常多这种工具&#xff0c;有一个…

全国计算机vb考试经典程序设计,全国计算机二级《VB语言程序设计》考试要点...

全国计算机二级《VB语言程序设计》考试要点VB语言程序设计是计算机二级考试的科目之一&#xff0c;考生们在备考是要熟悉科目的知识要点&#xff0c;有针对性地进行备考。下面百分网小编为大家搜索整理了关于二级《VB语言程序设计》考试要点&#xff0c;欢迎参考练习&#xff0…

MipMap

MipMap首先从MIPMAP的原理说起&#xff0c;它是把一张贴图按照2的倍数进行缩小。直到1X1。把缩小的图都存储起来。在渲染时&#xff0c;根据一个像素离眼睛为之的距离&#xff0c;来判断从一个合适的图层中取出texel颜色赋值给像素。在D3D和OGL都有相对应的API控制接 透过它的工…

计算机一级繁体字转换,繁体字转换器

有的朋友偏爱繁体字书写对联&#xff0c;繁体字对联看着也更端庄大气&#xff0c;今天出国留学网小编给大家整理提供了关于春节对联繁体字的精彩内容&#xff0c;欢迎阅读。通用春节对联大全带横批1. 上联&#xff1a;大順大財大吉利下联&#xff1a;新春新喜新世紀【橫批】&am…

ln 命令

ln是linux中又一个非常重要命令&#xff0c;它的功能是为某一个文件在另外一个位置建立一个同步的链接.当我们需要在不同的目录&#xff0c;用到相同的文件时&#xff0c;我们不需要在每一个需要的目录下都放一个必须相同的文件&#xff0c;我们只要在某个固定的目录&#xff0…

行内元素中间出现空隙

设置父级为font-size:0;转载于:https://www.cnblogs.com/yaser/p/4379572.html

windows2016服务器优化,Windows Server 2012 服务器优化图文方法

这篇文章主要介绍了Windows Server 2012 服务器优化图文方法,需要的朋友可以参考下1、显示桌面图片按下WinR键输入&#xff1a;rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,02、关闭IE增强的安全配置1.开启【服务器管理员】单击"服务器管理员"2.在左边窗格切…

StringBuffer与StringBuilder

有些时候&#xff0c;需要由较短的字符串构建字符串。比如&#xff0c;按键或来自文件中的单词。采用字符串连接的方式达到此目的效率比较低。每次连接字符串的时候&#xff0c;都会构建一个新的String对象&#xff0c;既耗时&#xff0c;又浪费空间。使用StringBuilder类就可以…

ExtJs控件属性配置详细(转)

序言&#xff1a; 1.本文摘自网络&#xff0c;看控件命名像是4.0以前的版本&#xff0c;但控件属性配置仍然可以借鉴&#xff08;不足之处&#xff0c;以后项目用到时再续完善&#xff09;。 Ext.form.TimeField: 配置项&#xff1a; maxValue&#xff1a;列表中允许…

网站服务器中病毒该如何处理,网站被中了木马无法删除怎么办? 解决网站中病毒的办法...

紧急预警“XXCMS整站系统(XXCMS)”官方安装包被植入后门这是我们 前几天在站长网上公布的紧急预警! 但是还是有人中招了&#xff0c;服务器中了马&#xff0c;导致网站被挂了黑链&#xff0c;我们外星人源码安全小姐紧急响应&#xff0c;马上为其清除木马后门&#xff0c;查杀病…

ThinkPHP 的URL重写时遇到No input file specified的解决方法

因为在Fastcgi模式下&#xff0c;php不支持rewrite的目标网址的PATH_INFO的解析 ThinkPHP运行在URL_MODEL2时&#xff0c;会出现 No input file specified.的情况&#xff0c; 这时可以修改网站目录的.htaccess文件&#xff1a; RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L] …

sql语句中----删除表数据drop、truncate和delete的用法

说到删除表数据的关键字,大家记得最多的可能就是delete了 然而我们做数据库开发,读取数据库数据.对另外的两兄弟用得就比较少了 现在来介绍另外两个兄弟,都是删除表数据的,其实也是很容易理解的 老大------drop 出没场合:drop table tb --tb表示数据表的名字,下同 绝招:删除内…