首页 > Java > java教程 > 正文

java双重检验锁模式是什么

WBOY
发布: 2023-05-19 15:29:49
转载
1552人浏览过

起因

在对项目进行pmd静态代码检测时,遇到了这样一个问题

Partially created objects can be returned by the Double Checked Locking pattern when used in Java. An optimizing JRE may assign a reference to the baz variable before it calls the constructor of the object the reference points to.Note: With Java 5, you can make Double checked locking work, if you declare the variable to be volatile.

可能在使用双重检验锁模式时,会返回一个未完全初始化的对象。有些人可能会怀疑部分初始化对象的概念,请继续往下分析

什么是双重检验锁模式

public static Singleton getSingleton() {<br/>    if (instance == null) {                        <br/>        synchronized (Singleton.class) {<br/>            if (instance == null) {                 <br/>                instance = new Singleton();<br/>            }<br/>        }<br/>    }<br/>    return instance ;<br/>} 
登录后复制

我们看到,在同步代码块的内部和外部都判断了instance == null,这是因为,可能会有多个线程同时进入到同步代码块外的if判断中,如果在同步代码块内部不进行判空的话,可能会初始化多个实例。 

问题所在

这种写法看似完美无缺,但它却是有问题的,或者说它并不担保一定完美无缺。主要原因在于instance = new Singleton();并不是原子性的操作。
创建一个对象可以分为三部:

1.分配对象的内存空间<br/>2.初始化对象<br/>3.设置instance指向刚分配的内存地址<br/>当instance指向分配地址时,instance是不为null的 
登录后复制

但是,2、3步之间,可能会被重排序,造成创建对象顺序变为1-3-2.试想一个场景:
线程A第一次创建对象Singleton,对象创建顺序为1-3-2;
当给instance分配完内存后,这时来了一个线程B调用了getSingleton()方法
这时候进行instance == null的判断,发现instance并不为null。
但注意这时候instance并没有初始化对象,线程B则会将这个未初始化完成的对象返回。那B线程使用instance时就可能会出现问题,这就是双重检查锁问题所在。 

立即学习Java免费学习笔记(深入)”;

使用volatile

对于上述的问题,我们可以通过把instance声明为volatile型来解决

public class Singleton{<br/>    private volatile static Singleton instance;<br/>    public static Singleton getSingleton() {<br/>        if (instance == null) {                        <br/>            synchronized (Singleton.class) {<br/>                if (instance == null) {                 <br/>                    instance = new Singleton();<br/>                }<br/>            }<br/>        }<br/>        return instance ;<br/>    }<br/>} 
登录后复制

但是必须在JDK5版本以上使用。 

静态内部类

public class Singleton {  <br/>    private static class SingletonHolder {  <br/>        private static final Singleton INSTANCE = new Singleton();  <br/>    }  <br/>    private Singleton (){}  <br/>    public static final Singleton getInstance() {  <br/>        return SingletonHolder.INSTANCE; <br/>    }  <br/>}
登录后复制

目前比较推荐的写法是采用静态内部类的方式,既能够实现懒加载,又不会出现线程安全问题。而且减少了synchronized的开销。

以上就是java双重检验锁模式是什么的详细内容,更多请关注php中文网其它相关文章!

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载
来源:亿速云网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号