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 下, 安装Android Studio
Download the Android Package of Linux from Android Studio, android-studio-bundle-130.737825-linux.tg ...
- cocos2d-x游戏之2048
学习游戏编程是一件非常有趣的事情,在cocos2dx官网找了几个简单的游戏试试手,感觉也不是那么难,首先来看看2048这款游戏吧,很火的原因之一是因为它简单而易操作.网上这位Legendof1991大 ...
- Sleep 和 Wait 关于锁释放的区别
sleep和wait的区别是一个老生常谈的问题.Sleep 是 Thread类的方法, wait是Object类的方法.但是关键的区别是对锁的操作问题. 当我们调用sleep的时候,线程进入休眠,但是 ...
- 详细讲解:通过composer安装TP5.1(Thinkphp5.1)
现在TP5越来越火了,TP5也更新到了5.1版本,但是5.1以上版本只能通过composer来进行安装,那么这里贴出详细的步骤 前提:PHP版本必须要5.6以上 参考网址:http://www.thi ...
- 如何用代码的方式取出SAP C4C销售订单创建后所有业务伙伴的数据
比如我创建了一个Sales Order(销售订单)后,如何用代码的方式取出这些通过SAP Partner determination自动填充的Involved Parties信息呢? 一种方法可以使用 ...
- java的sleep方法详解
java的sleep方法详解: sleep并不是永久占有CPU,没有那个线程能永久占用CPU.它是指在自己时间片内睡眠,而不是急着交出CPU.yield()就是自己愿意立即交出时间片.因此一个线程sl ...
- centos6 编译安装gcc4.8.2
12 wget http://ftp.tsukuba.wide.ad.jp/software/gcc/releases/gcc-4.8.2/gcc-4.8.2.tar.gz 13 rm -r -f g ...
- SVN知识集合
1. 如果某个项目之前保存了A仓库的信息,无法切换到B仓库(通过AnkhSVN或者VisualSVN),可以先在本地去除版本控制(用TortoiseSVN),然后导出B仓库信息(用TortoiseSV ...
- Java小吐槽
简单说明,所有小吐槽都基于我的.NET经验,作为Java初学者,肯定有贻笑大方之处,欢迎之处,共同学习,共同进步. 1. The public type XXXXXXXX must be define ...
- 剑指offer52 构建乘积数组
这个题的错误和c++ primier中名字的作用域例子相似.只是这里将int换成了vecto<int>这种形式. class Solution { public: vector<in ...