双重检查锁定(Double check locked)模式经常会出现在一些框架源码中,目的是为了延迟初始化变量.这个模式还可以用来创建单例.下面来看一个 Spring 中双重检查锁定的例子. 这个例子中需要将配置文件加载到 handlerMappings中,由于读取资源比较耗时,所以将动作放到真正需要 handlerMappings 的时候.我们可以看到 handlerMappings 前面使用了volatile .有没有想过为什么一定需要 volatile?虽然之前了解了双重检查锁定模式的原理…
单例类在Java开发者中非常常用,但是它给初级开发者们造成了很多挑战.他们所面对的其中一个关键挑战是,怎样确保单例类的行为是单例?也就是说,无论任何原因,如何防止单例类有多个实例.在整个应用生命周期中,要保证只有一个单例类的实例被创建,双重检查锁(Double checked locking of Singleton)是一种实现方法.顾名思义,在双重检查锁中,代码会检查两次单例类是否有已存在的实例,一次加锁一次不加锁,一次确保不会有多个实例被创建.顺便提一下,在JDK1.5中,Java修复了其内…
前言 从Java内存模型出发,结合并发编程中的原子性.可见性.有序性三个角度分析volatile所起的作用,并从汇编角度大致说了volatile的原理,说明了该关键字的应用场景:在这补充一点,分析下volatile是怎么在单例模式中避免双检锁出现的问题的.   并发编程的3个条件 1.原子性:要实现原子性方式较多,可用synchronized.lock加锁,AtomicInteger等,但volatile关键字是无法保证原子性的: 2.可见性:要实现可见性,也可用synchronized.loc…
背景:我们在实现单例模式的时候往往会忽略掉多线程的情况,就是写的代码在单线程的情况下是没问题的,但是一碰到多个线程的时候,由于代码没写好,就会引发很多问题,而且这些问题都是很隐蔽和很难排查的. 例子1:没有volatile修饰的uniqueInstance public class Singleton { private static Singleton uniqueInstance; private Singleton(){ } public static Singleton getInsta…
Java基础教程:多线程杂谈——双重检查锁与Volatile 双重检查锁 有时候可能需要推迟一些高开销的对象初始化操作,并且只有在使用这些对象时才进行初始化.此时程序员可能会采用延迟初始化.但要正确实现线程安全的延迟初始化需要一些技巧,否则很容易出现问题.比如,下面是非线程安全的延迟初始化对象的示例代码: public class A{ private Instance instance; public Instance getInstance(){ if(instance==null){ in…
对象部分初始化:原理以及验证代码(双重检查锁与volatile相关) 对象部分初始化被称为 Partially initialized objects / Partially constructed objects / Incompletely initialized objects 这三种不同的说法描述的是同一种情况,即指令重排序(reorder)导致未完全初始化的对象被使用,这会导致某些错误的发生. 文章纯原创,转载请表明地址 目录 对象部分初始化:原理以及验证代码(双重检查锁与volati…
最初的代码 在最近的项目中,写出了这样的一段代码 private static SomeClass instance; public SomeClass getInstance() { if (null == instance) { instance = new SomeClass(); } return instance; } 然后在Code Review的时候被告知在多线程的情况下,这样写可能会导致instance有多个实例.比如下面这种情况: Time Thread A Thread B…
一个典型的单例模式构建对象的双重检查锁如下: static Singleton * getSingleObject() { if(singleObject==NULL) { lock(); if(singleObject==NULL) { singleObject = new Singleton(); } unlock(); } return singleObject; } 该代码的逻辑是:getSingleObject()函数获得对象,如果对象不存在则创建,反之则直接返回.考虑到线程安全,创建…
搬以前写的博客[2014-12-30 16:04] 在web应用中服务器面临的是大量的访问请求,免不了多线程程序,但是有时候,我们希望在多线程应用中的某一个类只能新建一个对象的时候,就会遇到问题. 首先考虑单线程,如果要求只能新建一个对象,那么构造函数我们要设为private.简单的想法: class singleton{ private singleton(){ //..... } private static singleton instance; public static singlet…
并发编程情况下有三个要点:操作的原子性.可见性.有序性. volatile保证了可见性和有序性,但是并不能保证原子性. 首先看一下DCL(双重检验锁)的实现: public class Singleton { private volatile static Singleton singleton; private Singleton (){} public static Singleton getSingleton() { if (singleton == null) { synchronize…