首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

双重检查为什么要使用volatile字段?

双重的由来 单例模式中,有一个DCL(双重)的实现方式。在Java程序中,有时候可能需要推迟一些高开销的对象初始化操作,并且只有在使用这些对象时才开始初始化。...后来,提出了一个“聪明”的技巧:双重检查锁定(Double-Checked Locking)。想通过双重检查锁定来降低同步的开销。下面是使用双重检查锁定来实现延迟初始化的实例代码。.../** * 双重检查锁定 * * @author xiaoshu */ public class DoubleCheckedLocking { private static Instance...问题的根源 前面的双重检查锁定实例代码的第4处(instance = new Instance();)创建了一个对象。这一行代码可以分解为如下的3行伪代码。...在执行类的初始化期间,JVM会去获取一个.这个可以同步多个线程对同一个类的初始化。

1.3K10

服务端性能优化之双重检查

简介 早前的文章中讨论过服务端性能优化之异步查询转同步,在本文中,将讨论双重检查锁定设计模式。通过简单地事先检查锁定条件,该模式减少了锁定获取的次数,通常可以提高性能。...下面是之前关于和线程安全的文章的一些文章: Java服务端两个常见的并发错误 操作的原子性与线程安全 快看,i++真的不安全 原子操作组合与线程安全 单例的Demo 首先,让我们看一个具有严格同步的简单单例...要解决此问题,我们可以首先验证是否需要首先创建对象,只有在这种情况下,我们才能获取。...替代方案 即使经过双重检查的锁定可能会加快速度,但它至少存在两个问题: 由于它要求volatile关键字才能正常工作,因此它与Java 1.4及更低版本不兼容 它很冗长,使代码难以阅读 由于这些原因,让我们研究没有这些缺陷的其他方案...在本文时,这被认为是编写单例的最简洁,最安全的方法: public enum EnumSingleton { INSTANCE; // 其他方法 } 总结 总而言之,这篇文章介绍了双重检查的锁定模式

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

    Java单例模式中双重检查的问题

    这些事实将导致代码失败,原因是双重检查锁定难于跟踪。在本文余下的部分里,我们将详细介绍双重检查锁定习语,从而理解它在何处失效。...这就是“双重检查锁定”名称的由来。将双重检查锁定习语应用到清单 3 的结果就是清单 4 。 清单 4....线程 2 获取 //1 处的检查 instance 是否为 null。...双重检查锁定背后的理论是完美的。不幸地是,现实完全不同。双重检查锁定的问题是:并不能保证它会在单处理器或多处理器计算机上顺利运行。...双重检查锁定:获取两个 考虑到当前的双重检查锁定不起作用,我加入了另一个版本的代码,如清单 7 所示,从而防止您刚才看到的无序写入问题。 清单 7.

    1.9K20

    单例模式-双重检查(DCL)和volatile 的应用

    单例模式-双重检查(DCL, 即 double-checked locking) 代码示例如下: package com.hsy.demo; /** * 懒汉单例 * * 优点:懒加载,线程安全...} } } return lazySingleton; } } 解释说明 优点:懒加载,线程安全,效率较⾼ 缺点:实现较复杂 这⾥的双重检查是指两次...⾮空判断,指的是 synchronized 加锁,为什么要进⾏双重判断,其实很简单,第⼀重判断,如果实例已经存在,那么就不再需要进⾏同步操作,⽽是直接返回这个实例,如果没有创建,才会进⼊同步块,同步块的...关于内部的第⼆重空判断的作⽤,当多个线程⼀起到达位置时,进⾏竞争,其中⼀个线程获取,如果是第⼀次进⼊则为 null,会进⾏单例对象的创建,完成后释放,其他线程获取后就会被空判断拦截,直接返回已创建的单例对象...简单说明⼀下,双重检查中使⽤ volatile 的两个重要特性:可⻅性、禁⽌指令重排序。 这⾥为什么要使⽤ volatile ?

    77330

    单例模式双重检查模式为什么必须加 volatile?

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

    1.2K30

    双重检查单例模式为什么要用volatile关键字?

    双重检查锁定(Double check locked)模式经常会出现在一些框架源码中,目的是为了延迟初始化变量。...下面来看一个 Spring 中双重检查锁定的例子。...这个方法首先判断变量是否被初始化,没有被初始化,再去获取。获取之后,再次判断变量是否被初始化。第二次判断目的在于有可能其他线程获取过,已经初始化改变量。第二次检查还未通过,才会真正初始化变量。...这个方法检查判定两次,并使用,所以形象称为双重检查锁定模式。 这个方案缩小的范围,减少的开销,看起来很完美。然而这个方案有一些问题却很容易被忽略。...上面错误双重检查锁定的示例代码中,如果线程 1 获取到进入创建对象实例,这个时候发生了指令重排序。

    2.1K00

    双重检查,原来是这样演变来的,你了解吗

    在看Nacos的源代码时,发现多处都使用了“双重检查”的机制,算是非常好的实践案例。这篇文章就着案例来分析一下双重检查的使用以及优势所在,目的就是让你的代码格调更加高一个层次。...同时,基于单例模式,讲解一下双重检查的演变过程。...上述过程,在锁定前和锁定之后,做了两次判断,因此称作”双重检查“。使用的目的就是避免创建多个ConcurrentHashSet。...Nacos中的实例稍微复杂一下,下面以单例模式中的双重检查的演变过程。...双重检查 针对上面的问题,就有了双重检查,示例如下: public class Singleton { private static Singleton instance;

    52120

    双重检查锁定及单例模式

    在 Java 编程语言中,双重检查锁定就是这样的一个绝不应该使用的习语。在本文中,Peter Haggar 介绍了双重检查锁定习语的渊源,开发它的原因和它失效的原因。...这些事实将导致代码失败,原因是双重检查锁定难于跟踪。在本文余下的部分里,我们将详细介绍双重检查锁定习语,从而理解它在何处失效。...---- 回页首 双重检查锁定 为处理清单 3 中的问题,我们需要对 instance 进行第二次检查。这就是“双重检查锁定”名称的由来。将双重检查锁定习语应用到清单 3 的结果就是清单 4 。...线程 2 获取 //1 处的检查 instance 是否为 null。...双重检查锁定背后的理论是完美的。不幸地是,现实完全不同。双重检查锁定的问题是:并不能保证它会在单处理器或多处理器计算机上顺利运行。

    1.8K30

    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的使用没有让第一个检查线程安全

    51910

    速读原著-双重检查锁定与延迟初始化

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

    63010

    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 如上是一段单例模式中的懒汉模式双重检验...,这个时候发生了指令重排,线程A执行到t3时刻,此时线程B抢占了CPU执行时间片,但是由于此时对象不为空,则直接返回对象出去,然而使用该对象却发现该对象未被初始化就会报错,并且从始至终,线程B无需获取...双重检验问题解决方案 回头看下我们出问题的双重检查程序,它是满足as-if-serial语义的吗?是的,单线程下它没有任何问题,但是在多线程下,会因为重排序出现问题。

    47930
    领券