java线程安全(单例模式)(转载)
原文链接:http://www.jameswxx.com/java/%E8%AF%B4%E8%AF%B4%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F/
单例模式?多么简单!也许吧,可是要通过简单的现象,看到问题的本质,就比较难,知其然而不知其所以然,这种态度不好。
一:看看最简单的
public class SingleInstance{
private static instance=new SinleInstance();
public static SingleInstance getInstance(){
return instance;
}
}
这个很明了,也确实会返回唯一的实例,但是如果我永远都不会用到SingleInstance.getInstance(),instance这个对象却一直存在,占用了内存空间,浪费。
二:那就不先实例化
public class SingleInstance{
private static SingleInstance instance;
public static SingleInstance getInstance(){
if(instance==null){
instance=new SingleInstance();
}
return instance;
}
}
表面上,这个似乎是可行的。但是很显然,在多线程并发环境中,可能会创建两个instance,也有可能一个线程拿到的instance是一个不完整的实例。
三:好吧,那我加上同步总可以吧
public class SingleInstance{
private static SingleInstance instance;
public static synchronized SingleInstance getInstance(){
if(instance==null){
instance=new SingleInstance();
}
return instance;
}
}
这个虽然不会有内存上的浪费,但是有同步锁住了整个class,会降低系统的性能。按照数据结构的说法,就是一个提高了空间复杂度,一个提高了时间复杂度。
四:最佳实践
比较好的做法
public class SingleInstance {
private static class InstanceHolder {
public static final SingleInstance instance = new SingleInstance();
}
public static SingleInstance getInstance() {
return InstanceHolder.instance;
}
}
这种Holder做法保证了实例在用到的时候才会创建,而且创建的实例肯定是唯一的。
五:所谓的DCL
下面这种做法是广为流传的所谓DCL(双重检查锁定)做法,这是没有正确理解java内存模型造成的,只保证了创建实例的原子性,而没有解决共享资源的可见性。
public class SingleInstance{
private static SingleInstance instance;
public static SingleInstance getInstance(){
if(instance==null){
synchronized(SingleInstance.class){
if(instance==null){
instance=new SingleInstance();
}
}
}
return instance;
}
}
表面上看,这个似乎确实没有什么问题呢,其实还是有问题的,虽然概率比较小,要深刻的理解为什么,必须要对java内存模型比较熟悉。对于instance的创建,某个时刻某个线程拿到了同步锁,将instance创建了,并且及时写回了主存。但是对于另一个线程而言,它不能及时“看到”instance变量的最新值。它的instance可能是工作内存里的而不是主内存里的,甚至更为糟糕的情况是,instance是主内存的,可它的某些属性是工作内存的,这会导致程序发生莫名其妙不可捉摸的错误。在平台级框架里,这会造成系统在高并发环境下不稳定,甚至造成致命的错误 。
java线程安全(单例模式)(转载)的更多相关文章
- 50 道 Java 线程面试题(转载自牛客网)
下面是 Java 线程相关的热门面试题,你可以用它来好好准备面试. 1) 什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.程序员可以通过它进行多处理 ...
- 深入了解java线程池(转载)
出处:http://www.cnblogs.com/dolphin0520/ 本文归作者海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责 ...
- 【转载】 Java线程面试题 Top 50
Java线程面试题 Top 50 不管你是新程序员还是老手,你一定在面试中遇到过有关线程的问题.Java语言一个重要的特点就是内置了对并发的支持,让Java大受企业和程序员 的欢迎.大多数待遇丰厚的J ...
- Java线程面试题 Top 50 (转载)
转载自:http://www.cnblogs.com/dolphin0520/p/3958019.html 原文链接:http://www.importnew.com/12773.html 本文由 ...
- 【多线程】Java线程面试题 Top 50(转载)
Java线程面试题 Top 50 原文链接:http://www.importnew.com/12773.html 本文由 ImportNew - 李 广 翻译自 javarevisited.欢迎 ...
- Java线程面试题 Top 50(转载)
原文链接:http://www.importnew.com/12773.html 本文由 ImportNew - 李 广 翻译自 javarevisited.欢迎加入Java小组.转载请参见文章末尾的 ...
- 【转载】Java线程面试题 Top 50
Java线程面试题 Top 50 2014/08/21 | 分类: 基础技术 | 4 条评论 | 标签: 多线程, 面试题 分享到:140 本文由 ImportNew - 李 广 翻译自 javare ...
- JAVA线程安全总结(转载)
JAVA线程安全总结(一) JAVA线程安全总结(二) 最近想将java基础的一些东西都整理整理,写下来,这是对知识的总结,也是一种乐趣.已经拟好了提纲,大概分为这几个主题: java线程安全,jav ...
- (转载)JAVA线程池管理
平时的开发中线程是个少不了的东西,比如tomcat里的servlet就是线程,没有线程我们如何提供多用户访问呢?不过很多刚开始接触线程的开发攻城师却在这个上面吃了不少苦头.怎么做一套简便的线程开发模式 ...
- Java线程面试题 Top 50【转载】
不管你是新程序员还是老手,你一定在面试中遇到过有关线程的问题.Java语言一个重要的特点就是内置了对并发的支持,让Java大受企业和程序员的欢迎.大多数待遇丰厚的Java开发职位都要求开发者精通多线程 ...
随机推荐
- linux脚本的source和reload
什么时候用reload?有些程序, 当你修改了配置文件后, 需要重启之后, 配置才能生效,但是 这个程序又不能 重启 , 如大公司的httpd服务 因此, 当你修改完了之后, 需要在不重启服务的情况下 ...
- [QualityCenter]QC是什么?发展历程是怎样?
QC,即Quality Center,是一个基于Web的测试管理工具.它可以组织和管理应用程序测试流程的所有阶段,包括制定测试需求.计划测试.执行测试和跟踪缺陷.此外,通过Quality Center ...
- SQL查询某一字段重复的数据
查询出重复记录 select * from 数据表 WHERE 重复记录字段 in ( select 重复记录字段 from 数据表 group by 重复记录字段 having count(重复记 ...
- ASP.NET Core - VSCode安装和配置
在深入了解ASP.NET Core之前先研究了下主要的两个开发工具(VS 2015和VS Code), VS 2015对Core的支持已经相当的完备,很多操作得到简化用起来很是方便.VS Code是微 ...
- 网页打开速度优化——HTTP请求头及响应头
no-cache:不缓存过期的资源 no-store:不缓存 最近看了<图解HTTP>这本书,书上讲到了这两者的区别: no-cache从字面意义上很容易误解为不缓存,但是no-cache ...
- ABAP Netweaver和Hybris Enterprise Commerce Platform的登录认证
ABAP Netweaver 在我的博客Learn more detail about Standard logon procedure里有详细介绍. Hybris ECP Hybris Admini ...
- 【JavaScript 封装库】BETA 2.0 测试版发布!
/* 源码作者: 石不易(Louis Shi) 联系方式: http://www.shibuyi.net =============================================== ...
- EF写distinct
在日常开发中常常是这么写的 var logErrorRequest = from l in _logErrorRepository.Table select new { WrongTime = l.W ...
- SSM框架整合:转自:http://blog.csdn.net/zhshulin
使用SSM(Spring.SpringMVC和Mybatis)已经有三个多月了,项目在技术上已经没有什么难点了,基于现有的技术就可以实现想要的功能,当然肯定有很多可以改进的地方.之前没有记录SSM整合 ...
- redis 系列 在 vs上 set,get 键值
1.启动两个 cmd,一个用于打开服务,一个用于运行客户端. 详细步骤可见上一篇文章 2.下载nuget的 ServiceStack.Redis; ,并在using中引用 ,详细步骤可见上一篇文章 ...