Java并发(七):双重检验锁定DCL
双重检查锁定(Double Check Lock,DCL)
1、懒汉式单例模式,无法保证线程安全:
public class Singleton {
private static Singleton singleton;
private Singleton() {
}
public static Singleton getInstance() {
if (singleton == null) {// 多个线程同时执行到此,会生成多个Singleton实例
singleton = new Singleton();
}
return singleton;
}
}
2、同步处理,synchronized就会导致这个方法比较低效:
public class Singleton {
private static Singleton singleton;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
3、双重检查 DCL:
public class Singleton {
private static Singleton singleton;
Integer a;
private Singleton(){}
public static Singleton getInstance(){
if(singleton == null){ // 1 只有singleton==null时才加锁,性能好
synchronized (Singleton.class){ //
if(singleton == null){ //
singleton = new Singleton(); //
}
}
}
return singleton;
}
}
但是,仍然有问题!!
创建对象过程:
(1)分配内存空间
(2)初始化对象
(3)将内存空间的地址赋值给对应的引用
(2)(3)会被处理器优化,发生重排序
举例:
A线程singleton = new Singleton()发生重排序,将分配的内存空间引用赋值给了静态属性singleton(即singleton != null),而对象还未初始化(即Integer a == null);
B线程此时调用getInstance()方法,因为singleton != null,直接返回singleton。当B线程使用singleton的a属性时就会空指针。

分析:
问题在于singleton = new Singleton()的重排序
(1)不允许初始化阶段步骤2 、3发生重排序。
(2)允许初始化阶段步骤2 、3发生重排序,但是不允许其他线程“看到”这个重排序。
解决:
1、利用volatile限制重排序
public class Singleton {
private volatile static Singleton singleton;// 通过volatile关键字来确保安全
private Singleton(){}
public static Singleton getInstance(){
if(singleton == null){
synchronized (Singleton.class){
if(singleton == null){
singleton = new Singleton();
}
}
}
return singleton;
}
}
(1)分配内存空间
(2)初始化对象
(3)将内存空间的地址赋值给对应的引用
第(3)步 volatile修饰的变量singleton的写入操作,通过内存屏障限制的重排序 参考:Java并发(六):volatile的实现原理
2、利用类初始化
JVM会保证一个类的类构造器在多线程环境中被正确的加锁、同步,如果多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的类构造器,其他线程都需要阻塞等待,直到活动线程执行方法完毕。
特别需要注意的是,在这种情形下,其他线程虽然会被阻塞,但如果执行初始化的那条线程退出后,其他线程在唤醒之后不会再次进入/执行初始化,因为在同一个类加载器下,一个类型只会被初始化一次。
public class Singleton {
private static class SingletonHolder{
public static Singleton singleton = new Singleton();
}
public static Singleton getInstance(){
return SingletonHolder.singleton;
}
}
参考资料:
【死磕Java并发】—–Java内存模型之从JMM角度分析DCL
Java并发(七):双重检验锁定DCL的更多相关文章
- Java盲点:双重检查锁定及单例模式
尊重原创: http://gstarwd.iteye.com/blog/692937 2004 年 5 月 01 日 所有的编程语言都有一些共用的习语.了解和使用一些习语很有用,程序员们花费宝贵的时间 ...
- JAVA并发七(多线程环境中安全使用集合API)
在集合API中,最初设计的Vector和Hashtable是多线程安全的.例如:对于Vector来说,用来添加和删除元素的方法是同步的.如果只有一个线程与Vector的实例交互,那么,要求获取和释放对 ...
- java 并发(七)--- ThreadLocal
文章部分图片来自参考资料 问题 : ThreadLocal 底层原理 ThreadLocal 需要注意什么问题,造成问题的原因是什么,防护措施是什么 ThreadLocal 概述 Threa ...
- Java并发--三大性质
一.多线程的三大性质 原子性:可见性.有序性 二.原子性 原子性介绍 原子性是指:一个操作时不可能中断的,要么全部执行成功要么全部执行失败,有着同生共死的感觉.即使在多线程一起执行的时候,一个操作一旦 ...
- java并发编程系列七:volatile和sinchronized底层实现原理
一.线程安全 1. 怎样让多线程下的类安全起来 无状态.加锁.让类不可变.栈封闭.安全的发布对象 2. 死锁 2.1 死锁概念及解决死锁的原则 一定发生在多个线程争夺多个资源里的情况下,发生的原因是 ...
- DCL,即Double Check Lock,中卫双重检查锁定。
DCL,即Double Check Lock,中卫双重检查锁定. [Java并发编程]之十六:深入Java内存模型——happen-before规则及其对DCL的分析(含代码) 关于单例.关于DCL: ...
- java中的双重锁定检查(Double Check Lock)
原文:http://www.infoq.com/cn/articles/double-checked-locking-with-delay-initialization#theCommentsSect ...
- Java并发——DCL问题
转自:http://www.iteye.com/topic/875420 如果你搜索网上分析dcl为什么在java中失效的原因,都会谈到编译器会做优化云云,我相信大家看到这个一定会觉得很沮丧.很无助, ...
- JAVA 双重检查锁定和延迟初始化
双重检查锁定的由来在Java程序中,有时需要推迟一些高开销的对象的初始化操作,并且只有在真正使用到这个对象的时候,才进行初始化,此时,就需要延迟初始化技术.延迟初始化的正确实现是需要一些技巧的,否则容 ...
随机推荐
- 【leetcode 简单】第三十一题 买卖股票的最佳时机
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. 如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润. 注意你不能在买入股票前卖出股票. 示例 ...
- 2017ACM暑期多校联合训练 - Team 5 1006 HDU 5205 Rikka with Graph (找规律)
题目链接 Problem Description As we know, Rikka is poor at math. Yuta is worrying about this situation, s ...
- HDU 1754 I Hate It (线段树)
题目链接 Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少. 这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老 ...
- div遮罩实现禁用鼠标(click、hover等)事件
这两天在帮老师做网页,今天想实现在一块区域内禁止鼠标的各种事件,本来是想在框架模板的js文件里去修改,但是改代码的时候有点凌乱...感觉应该自己把问题想复杂了. 所以想了想要是能实现在一个区域内(如: ...
- FastStoneCapture(FSCapture)录屏、剪辑教程
FastStoneCapture软件编辑视频的使用方法: http://www.tudou.com/programs/view/2eD-s5HP1xw/
- bootstrap通过ajax请求JSON数据后填充到模态框
1. JSP页面中准备模态框 <!-- 详细信息模态框(Modal) --> <div> <div class="modal fade" id=& ...
- OGG生成数据定义文件的参数NOEXTATTR
./defgen paramfile ./dirprm/jzjj.prm NOEXTATTR In OGG 11.2, there is a new parameter NOEXTATTR. This ...
- PHP中的 get_magic_quotes_runtime
get_magic_quotes_runtime() 获得外部文件及数据库资料时是否进行转义 set_magic_quotes_runtime(1); 临时设置获得外部文件及数据库资料时是否进行转义 ...
- dm368 ipnc3.0环境搭建脚本
前言 为了方便其他人搭建dm368 ipnc3.0环境,我写了个脚本,执行脚本就可以自动搭建好环境了,绝对的傻瓜操作了,不过有一个地方让我很郁闷,那就是在用sed替换掉某段内容的时候(143行--15 ...
- Google Gapps – Download Gapps for Android【转】
http://wiki.rootzwiki.com/Google_Apps http://productforums.google.com/forum/#!forum/apps http://www. ...