展开

关键词

定 - Double checked locking,是一种单例的方式。 其中的有序性意思是指令的执行顺序不会被新排列。 ,排序后的结果不受影响,但是就会导致单例失效的问题。 可以认为在实例化的//3语句结束后就释放了,因此排序会导致在mInstance仍然为null的时候第二个线程就进入了。 volatile在阻止了排序之后,第二个线程只能在 instance正确初始化并不为 null的情况下才能获取,所以 volatile避免了DCL被破坏的情况。

17410

定与单例

的单例 下面是我们经常使用的一种单例的实现,也就是所的实现方案。 } } } return uniqueSingleton; } } 让我们来看一下这个代码是如何工作的:首先当一个线程发出请求后,会先 解决方案 对于上面的问题,有两种解决方案 1,使用 volatile 关键词主要可以保证代码的执行顺序不受 jvm 排序影响。

30630
  • 广告
    关闭

    腾讯云618采购季来袭!

    一键领取预热专享618元代金券,2核2G云服务器爆品秒杀低至18元!云产品首单低0.8折起,企业用户购买域名1元起…

  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    定及单例模式

    在 Java 编程语言中,定就是这样的一个绝不应该使用的习语。在本文中,Peter Haggar 介绍了定习语的渊源,开发它的原因和它失效的原因。 这些事实将导致代码失败,原因是定难于跟踪。在本文余下的部分里,我们将详细介绍定习语,从而理解它在何处失效。 ---- 回页首 定 为处理清单 3 中的问题,我们需要对 instance 进行第二次。这就是“定”名称的由来。将定习语应用到清单 3 的结果就是清单 4 。 定背后的理论是完美的。不幸地是,现实完全不同。定的问题是:并不能保证它会在单处理器或多处理器计算机上顺利运行。 ---- 回页首 定:获取两个 考虑到当前的定不起作用,我加入了另一个版本的代码,如清单 7 所示,从而防止您刚才看到的无序写入问题。 清单 7.

    83330

    服务端性能优化之

    简介 早前的文章中讨论过服务端性能优化之异步询转同步,在本文中,将讨论定设计模式。通过简单地事先定条件,该模式减少了定获取的次数,通常可以提高性能。 更进一步,我们想在进入同步块后立即再次执行相同的,以保持原子操作: public class DclSingleton { private static volatile DclSingleton 替代方案 即使经过定可能会加快速度,但它至少存在两个问题: 由于它要求volatile关键字才能正常工作,因此它与Java 1.4及更低版本不兼容 它很冗长,使代码难以阅读 由于这些原因,让我们研究没有这些缺陷的其他方案 在本文时,这被认为是编写单例的最简洁,最安全的方法: public enum EnumSingleton { INSTANCE; // 其他方法 } 总结 总而言之,这篇文章介绍了定模式 ---- 郑声明:文章首发于公众号“FunTester”,禁止第三方(腾讯云除外)转载、发表。

    23810

    为什么要使用volatile字段?

    后来,提出了一个“聪明”的技巧:定(Double-Checked Locking)。想通过定来降低同步的开销。下面是使用定来实现延迟初始化的实例代码。 /** * 定 * * @author xiaoshu */ public class DoubleCheckedLocking { private static Instance } } } return instance; } } 定看起来似乎很完美,但这是一个错误的优化 问题的根源 前面的定实例代码的第4处(instance = new Instance();)创建了一个对象。这一行代码可以分解为如下的3行伪代码。 解决方案一:基于volatile的解决方案 /** * 安全的定 * * @author xiaoshu */ public class SafeDoubleCheckedLocking

    53310

    java单例真的线程安全吗?

    相信大多数同学在面试当中都遇到过手写单例模式的题目,那么如何写一个完美的单例是面试者需要深究的问题,因为一个严谨的单例模式说不定就直接决定了面试结果,今天我们就要来讲讲看似线程安全的单例模式中可能会出现的指令排问题 ---- 单例模式 乍一看下面单例模式没啥问题,还加了同步保证线程安全,从表面上看确实看不出啥问题,当在同一时间多个线程同时执行该单例时就会出现JVM指令排的问题,从而可能导致某一个线程获取的 假设有A、B两个线程去调用该单例方法,当A线程执行到single = new Single()时,如果编译器和处理器对指令新排序,指令排后: //1:分配对象的内存空间 memory = allocate 、lock作用的代码块自然是有序执行的,volatile关键字有效的禁止了指令排序,实现了程序执行的有序性; 看完volatile关键字的特性之后我们应该就明白了,是volatile关键字禁止了指令排序从而解决了指令排的问题 更正后的单例 对比上面单例,下面单例在私有静态变量single前面加了修饰符volatile能够防止JVM指令排,从而解决了single对象可能出现成员变量未初始化的问题。

    69720

    速读原著-定与延迟初始化

    定与延迟初始化 在Java 程序中,有时候可能需要推迟一些高开销的对象初始化操作,并且只有在使用这些对象时才进行初始化。此时程序员可能会采用延迟初始化。 因此, 人们想出了一个“聪明”的技巧:定(double-checked locking)。人们想通过定来降低同步的开销。下面是使用定来实现延迟初始化的示例代码: ? 在对象创建好之后,执行getInstance()将不需要获取,直接返回已创建好的对象。 定看起来似乎很完美,但这是一个错误的优化! 基于volatile 的定的解决方案 对于前面的基于定来实现延迟初始化的方案(指 DoubleCheckedLocking 示例代码), 我们只需要做一点小的修改(把 instance 通过对比基于 volatile 的定的方案和基于类初始化的方案,我们会发现基于类初始化的方案的实现代码更简洁。

    18310

    单例模式为什么要用volatile关键字?

    ,实现了程序执行的有序性; 定模式 定(Double check locked)模式经常会出现在一些框架源码中,目的是为了延迟初始化变量。 下面来看一个 Spring 中定的例子。 这个方法判定两次,并使用,所以形象称为定模式。 这个方案缩小的范围,减少的开销,看起来很完美。然而这个方案有一些问题却很容易被忽略。 虽然排序并不影响单线程内的执行结果,但是在多线程的环境就带来一些问题。 上面错误定的示例代码中,如果线程 1 获取到进入创建对象实例,这个时候发生了指令排序。 注意,volatile禁止指令排序在 JDK 5 之后才被修复 使用局部变量优化性能 看 Spring 中定代码。

    91300

    单例模式模式为什么必须加 volatile?

    单例模式模式为什么必须加 volatile? 知道单例模式是一种很常见的设计模型,其目的就是为了避免创建过多的对象,给jvm造成比较大的压力,之前也对单例模型进行了比较详细的描述,详情参考我之前博客:链接 如果要实现一种线程安全的单例模型,一般都会采用模式 Singleton(); } } } return instance; } } 这里,就会有疑问,为什么要 答:这里分情况,如果不用第一个if判断,在多线程情况下,所有的线程都会进行抢,所以其实就是串行执行的;如果不用第二个if判断,因为经过第一个if判断,多个线程都会进来,不过只有一个线程能抢到,因为singleton 对象是null,所以会进行new Singleton,这种情况,如果不加第二个if判断,第一个线程创建对象之后,之后线程会继续创建的,所以这种就没做到单例 的原因知道之后,为什么要加volatile

    8430

    ,原来是这样演变来的,你了解吗

    在看Nacos的源代码时,发现多处都使用了“”的机制,算是非常好的实践案例。这篇文章就着案例来分析一下的使用以及优势所在,目的就是让你的代码格调更加高一个层次。 同时,基于单例模式,讲解一下的演变过程。 Nacos中的实例稍微复杂一下,下面以单例模式中的的演变过程。 针对上面的问题,就有了,示例如下: public class Singleton { private static Singleton instance; 再回顾一下本文的点: 阅读Nacos源码,发现的使用; 未加单例模式使用,会创建多个对象; 方法上加,导致性能下降; 代码内局部加判断,既满足线程安全,又满足性能需求; 单例模式特例

    9820

    并发学习笔记11-定与延迟初始化

    本文首发:windCoder.com 关于定,了解过单例的应该不陌生,但也容易写错。这里以单例模式为例一起探索。 为了继续优化,因此人们想出了一个“聪明”的技巧,即定(Double-Checked Locking,简称DCL): public class Singleton { public static Signleton getInstance() { // 3 if(instance == null) { // 4:第一次 6:第二次 instrance = new Singleton(); // 7:问题根源 } 在此期间,JVM会获取一个。这个可以同步多个线程对同一个类的初始化。

    38420

    java:基于volatile和Thread Local Storage的定实现延迟初始化

    下面这段很简单的基于定(Double-checked locking)实现的延迟初始化(Lazy initialization)代码,还是让spotbugs找出了问题(感谢spotbugs)。 } } } return filedNames; } 解决方案2 基于线程本地存储TLS(Thread Local Storage)实现定 * @return */ public T get(); } BaseVolatile.java package gu.simplemq; /** * 基于volatile的定实现 } return var; } } BaseTls.java package gu.simplemq; /** * 基于Thread Local Storage的定实现 》 《定失败可能性——参照《The “Double-Checked Locking is Broken” Declaration》》 《Java中Volatile关键字详解》

    43670

    java:基于volatile和Thread Local Storage的定实现延迟初始化

    下面这段很简单的基于定(Double-checked locking)实现的延迟初始化(Lazy initialization)代码,还是让spotbugs找出了问题(感谢spotbugs)。 doGetFieldNames(); } } } return filedNames; } #解决方案2 基于线程本地存储TLS(Thread Local Storage)实现定 实例 * @return */ public T get(); } ##BaseVolatile.java package gu.simplemq; /** * 基于volatile的定实现 } } } return var; } } ##BaseTls.java package gu.simplemq; /** * 基于Thread Local Storage的定实现 》][4] [《定失败可能性——参照《The “Double-Checked Locking is Broken” Declaration》》][5] [《Java中Volatile关键字详解

    21710

    C++核心准则CP.110:不要自已为初始化编写定代码

    CP.110: Do not write your own double-checked locking for initialization CP.110:不要自已为初始化编写定代码 Reason 在和RAII模式结合使用的时候,通过使用静态局部变量,可以消除自己为初始化编写定代码的需求。 Example(示例) Example with std::call_once. 有可能出这种惯用法么?

    14020

    C++核心准则CP.111:如果真的需要好,使用惯用模式

    CP.111: Use a conventional pattern if you really need double-checked locking CP.111:如果真的需要好,使用惯用模式 容易把事情搞杂。 如果你真的需要使用,而不管C++核心准则CP.100:不要使用无编程方式,除非绝对必要和C++核心准则CP.110:不要自已为初始化编写定代码中的建议,那么在使用时遵循惯用模式 当非线程安全动作很难发生,而且存在快速的线程安全测试可以用于保证不需要该动作,但是无法保证相反的情况,可以使用没有违背C++核心准则CP.110:不要自已为初始化编写定代码准则的模式 first check thread-safe, see also CP.200: Use volatile only to talk to non-C++ memory volatile的使用没有让第一个线程安全

    19310

    C++11单例设计模式(

    Solution();        还有一种是懒汉模式,顾名思义,当你需要用它的时候才去实例化对象,如果多个线程同时去实例化对象,那么产生的对象可能不唯一,所以存在线程安全的问题,避免这个线程安全的解决办法是用

    57710

    sentinel里的

    单例模式有很多种,饿汉式,懒汉式,,公司里大部分都是选择了,其中sentinel的ContextUtil源码里就有相关的实现: protected static Context trueEnter context.setOrigin(origin); contextHolder.set(context); } return context; } 上述代码使用了

    7620

    java安全编码指南之:

    简介 定模式是一种设计模式,我们通过首次定条件而不是实际获得从而减少获取的开销。 定模式用法通常用于实现执行延迟初始化的单例工厂模式。 但是我们需要非常小心的使用测模式,以避免发送错误。 在多线程环境中,因为排序的影响,我们可能的到意向不到的结果。 } } } return bookDLC; } } 我们先判断bookDLC是否为空,如果为空,说明需要实例化一个新的对象,这时候我们住 BookStatic getBookStatic(){ return bookStatic; } } JVM在类被加载之后和被线程使用之前,会进行静态初始化,而在这个初始化阶段将会获得一个

    18031

    单例模式--真的线程安全吗

    虽然容易,但里面的坑也有很多,比如模式(double checked locking pattern)真的是线程安全的吗? 起因 在对项目进行PMD静态代码测时,遇到了这样一个问题 Partially created objects can be returned by the Double Checked Locking 大概意思是,使用模式,可能会返回一个部分初始化的对象。 可能大家有些疑虑,什么是部分初始化的对象,我们下面继续分析 什么是模式 public static Singleton getSingleton() { if (instance == 那B线程使用instance时就可能会出现问题,这就是问题所在。

    65421

    JUC并发编程之单例模式陷阱

    1 前言 我在上一篇文章聊volatile的时候,埋下了一个问题,在并发情况下单例模式可能会存在的问题,那么本文就来详细分析分析它。 2 浅谈单例模式陷阱 首先看一段代码 public class Test04 { private static Test04 test04; public static Test04 } } //-----输出结果 com.dream.sunny.Test04@3f99bd52 com.dream.sunny.Test04@3f99bd52 true 如上是一段单例模式中的懒汉模式 ,线程B无需获取 针对以上情况,是否有解决方案,答案是有的,它问题出现在指令排,我前面有文章专门提到过这个现象,为了读者方便,我这里简单说明一下指令排是什么,具体可以看 "JUC并发编程之Volatile 问题解决方案 回头看下我们出问题的程序,它是满足as-if-serial语义的吗?是的,单线程下它没有任何问题,但是在多线程下,会因为排序出现问题。

    12230

    相关产品

    • 本地专用集群

      本地专用集群

      本地专用集群(CDC)是基础设施类产品,将中心化的公有云服务,延伸为可在客户机房落地的近场服务,融合公有云与本地IDC的双重优势,用户可以以本地化的时延和数据安全来使用公有云的丰富能力

    相关资讯

    热门标签

    扫码关注云+社区

    领取腾讯云代金券