单例模式 指令重排_php单例模式

单例模式 指令重排_php单例模式单例模式写法有很多,于是我看到了这么一种写法:publicclassSingletonTest{privateSingletonTest(){}privatestaticSingletonTestsingletonTest=null;publicstaticSingletonTestgetSingletonTest()…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

单例模式写法有很多,于是我看到了这么一种写法:

public class SingletonTest {

    private SingletonTest() {
    }

    private static SingletonTest singletonTest = null;

    public static SingletonTest getSingletonTest() {
        if (singletonTest == null) {
            // 若singletonTest为空,则加锁,再进一步判空
            synchronized (SingletonTest.class) {
                // 再判断一次是否为null
                if (singletonTest == null) {
                    //若为空,则创建一个新的实例
                    singletonTest = new SingletonTest();
                }
            }
        }
        return SingletonTest;
    }
}

这种写法算是一个考虑比较得当的设计了 为了防止多线程调用产生多个实例,采用了同步锁 加锁位置得当,尽可能降低了加锁对性能的影响 
但是在这个示例下方,有指出可能会由于指令重排的影响,导致代码执行错误,只是概率很低。

 

我不由得重新审视着这段代码,难道看似稳的一逼的代码如此不堪一击? 
于是,我大致了解了下指令重排: 
指令重排序是JVM为了优化指令,提高程序运行效率,在不影响单线程程序执行结果的前提下,尽可能地提高并行度。 
也就是说,JVM为了执行效率会将指令进行重新排序,但是这种重新排序不会对单线程程序产生影响。

首先,JVM是如何保证单线程下的指令在重新排序后执行结果不受影响的呢?

(此处省略一万字……关于happens-before,感兴趣的请看原文)

 由于singletonTest = new SingletonTest()操作并不是一个原子性指令,会被分为多个指令:

memory = allocate(); //1:分配对象的内存空间
ctorInstance(memory); //2:初始化对象
instance = memory; //3:设置instance指向刚分配的内存地址

但是经过重排序后如下:

memory = allocate(); //1:分配对象的内存空间
instance = memory; //3:设置instance指向刚分配的内存地址,此时对象还没被初始化
ctorInstance(memory); //2:初始化对象

 若有A线程进行完重排后的第二步,且未执行初始化对象。此时B线程来取singletonTest时,发现singletonTest不为空,于是便返回该值,但由于没有初始化完该对象,此时返回的对象是有问题的。这也就是为什么说看似稳的一逼的代码,实则不堪一击。 
另外,在《java并发编程实战》16.2.4中对该种双重检查加锁(DCL)提出了批评。批评的主要点在于,该方式会导致上述指出的取到一个无效或错误状态的对象。 
上述代码的改进方法:将singletonTest声明为volatile类型即可(volatile有内存屏障的功能)。

参考博客: https://www.cnblogs.com/senlinyang/p/7875458.html

 

 

节选自:https://blog.csdn.net/yuruixin_china/article/details/80550209

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/180992.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 3.3v与5v电平转换_5v电压经过10位A/D转换

    3.3v与5v电平转换_5v电压经过10位A/D转换问题背景在设计一个带MCU或者ARM系统电路时候,经常遇见MCU的VCC是3.3V,但是外围电路需要5V,有时候是反过来。虽然现在MCU的IO都声称支持TTL电平,但是我们谁也不想将MCU的IO口直接接上5V,即使IO口先串联一个电阻,然后再接上5V,这样总是不放心,担心烧掉MCU。再说了,MCU声称IO口支持TTL电平,但是并不是所有的IO都是这样,反正有隐患。解决方法就是电平转换。具体的我只说我在实际项目中运用到的方法,而且在项目中运用比较方便的,其他的都不再说了。法一:基于门电路第一种:利用O

    2022年8月10日
    11
  • PXE服务「建议收藏」

    PXE服务「建议收藏」PXE服务器简介PXE(prebootexecuteenvironment)是由Intel公司开发的最新技术,工作于Client/Server的网络模式,支持工作站通过网络从远端服务器下载映像,并由此支持来自网络的操作系统的启动过程,其启动过程中,终端要求服务器分配IP地址,再用TFTP(trivialfiletransferprotocol)或MTFTP(multicasttrivialfiletransferprotocol)协议下载一个启动软件包到本机内存中并执行,由这个启动软件包

    2025年6月11日
    3
  • 海思Hi3798MV100机顶盒芯片介绍[通俗易懂]

    海思Hi3798MV100机顶盒芯片介绍[通俗易懂]Hi3798MV100是海思推出的专门针对OTT机顶盒市场的高性价比芯片方案。在码流兼容性、在线视频播放的流畅性、图像质量以及整机性能方面保持业界最好的用户体验。集成四核高性能处理器、内置NEON,其处理性能可以满足各种差异化的业务需求,支持Dolby和DTS音频处理。支持H.265、H.264、AVS+、MVC、MPEG2、MPEG4、VC-1、VP6、VP8等多种格式的高清视频解码和高性…

    2022年6月15日
    89
  • tidb数据库隔离级别剖析

    tidb数据库隔离级别剖析本文章来源于:https://github.com/Zeb-D/my-review,请star强力支持,你的支持,就是我的动力。[TOC]前言在线应用业务中,数据库是一个非常重要的组成部分,特别是现在的微服务架构为了获得水平扩展能力,我们倾向于将状态都存储在数据库中,这要求数据库能够正确、高性能处理请求,但这是一个几乎不可能达到的要求,所以数据库的设计者们定义了隔离级别这一个概念,在高…

    2022年5月25日
    41
  • 企业微信机器人定时发送信息

    企业微信机器人定时发送信息企业微信可以配置机器人,提升办公效率,还能实现一键群发和定时发送等功能。

    2022年6月16日
    44
  • acwing-1080. 骑士(基环树dp)[通俗易懂]

    acwing-1080. 骑士(基环树dp)[通俗易懂]Z 国的骑士团是一个很有势力的组织,帮会中聚集了来自各地的精英。他们劫富济贫,惩恶扬善,受到了社会各界的赞扬。可是,最近发生了一件很可怕的事情:邪恶的 Y 国发起了一场针对 Z 国的侵略战争。战火绵延五百里,在和平环境中安逸了数百年的 Z 国又怎能抵挡得住 Y 国的军队。于是人们把所有希望都寄托在了骑士团身上,就像期待有一个真龙天子的降生,带领正义打败邪恶。骑士团是肯定具备打败邪恶势力的能力的,但是骑士们互相之间往往有一些矛盾。每个骑士有且仅有一个他自己最厌恶的骑士(当然不是他自己),他是绝对不

    2022年8月9日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号