public class Singleton {   

    /**
* 单例对象实例
*/
private volatile static Singleton instance = null; public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}

  这是一个典型的DCL单例,其中volatile在之前已经说过了,可以保证无论何时读取这个变量,都是读到内存中最新的值,无论何时写这个变量,都可以立即写到内存中。

  但是并没有这么简单,在没有见volatile修饰instance时,在编译后,编译器会自动把第二个判断删除,因为编译器判断这个程序在执行过程中,这个值是不会改变的,编译器不考虑多线程的情况。加了volatile,是告诉编译器,这个变量随时有可能会被其他线程改变,这样编译器就不会把这两个判断优化成一个判断了。

  同时,volatile的变量,可以保证对该变量的操作具有原子性,典型的例子是long和double型变量,通常需要分两步读写一个double变量,volatile修饰的double可以保证对一个double变量的操作的两部分不会被多线程插入。以及对引用类型赋值的,new一个实例的过程不会被其他线程插入(new在编译指令中是分成几步执行的,防止这几步在执行过程中被其他线程取这个变量值,取到一个不完整的实例)。可以简单的理解为对volatile变量的set和get方法加上了synchronized关键字,在new的过程中,整个都处在set中,所以不会被其他线程的get打断,取到不完整的引用。

  原子性针对一个long或者double或者一个引用类型,对于引用类型,原子性是指在new实例的过程中,不会被其他线程取到,即不会被其他线程取到一个不完整的实例。这种原子性可以理解为new的过程处于一个synchronize段的set方法中,只有set结束才可以被get到,即new的整个过程都是处于set中的。也可以理解为指令重排序,禁止把new过程的指令与把引用赋值给变量的语句重排序,赋值只发生在new结束之后。

  再次,在第二次判断if (instance == null)的时候,会再次取一次instance,再次取这个instance已经是所有线程最新的,每次修改的引用都会实时反映到主内存中。

关于单例的DCL方式分析的更多相关文章

  1. 关于java的volatile关键字与线程栈的内容以及单例的DCL

    用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的最新的值.volatile很容易被误用,用来进行原子性操作. package com.guangshan.test; pub ...

  2. Swift中编写单例的正确方式

    在之前的帖子里聊过状态管理有多痛苦,有时这是不可避免的.一个状态管理的例子大家都很熟悉,那就是单例.使用Swift时,有许多方法实现单例,这是个麻烦事,因为我们不知道哪个最合适.这里我们来回顾一下单例 ...

  3. Swift中的单例的实现方式

    单例在iOS日常开发中是一个很常用的模式.对于希望在 app 的生命周期中只应该存在一个的对象,保证对象的唯一性的时候,一般都会使用单例来实现功能.在OC单例的写法如下: @implementatio ...

  4. 单例---被废弃的DCL双重检查加锁

    被废弃的单例的DCL双重检查加锁/* *单例模式 *单例模式,保证一个类仅有一个实例,并提供一个访问它的全局访问点. *加同步锁的单例模式,适合在多线程中使用. */ class Singleton{ ...

  5. Redis 单例、主从模式、sentinel 以及集群的配置方式及优缺点对比(转)

    摘要: redis作为一种NoSql数据库,其提供了一种高效的缓存方案,本文则主要对其单例,主从模式,sentinel以及集群的配置方式进行说明,对比其优缺点,阐述redis作为一种缓存框架的高可用性 ...

  6. Hi,我们再来聊一聊Java的单例吧(转)

    1. 前言 单例(Singleton)应该是开发者们最熟悉的设计模式了,并且好像也是最容易实现的——基本上每个开发者都能够随手写出——但是,真的是这样吗? 作为一个Java开发者,也许你觉得自己对单例 ...

  7. Unity 游戏框架搭建 2018 (二) 单例的模板与最佳实践

    Unity 游戏框架搭建 2018 (二) 单例的模板与最佳实践 背景 很多开发者或者有经验的老手都会建议尽量不要用单例模式,这是有原因的. 单例模式是设计模式中最简单的也是大家通常最先接触的一种设计 ...

  8. 探索Scala(3)-- 单例对象

    研究一下Scala语言的单例对象(Singleton Objects),为下一篇文章做准备. static不是keyword 上一篇文章提到过,interface并非Scala语言keyword,能够 ...

  9. java单例五种实现模式梳理

    java单例五种实现模式 饿汉式(线程安全,调用效率高,但是不能延时加载) 一上来就把单例对象创建出来了,要用的时候直接返回即可,这种可以说是单例模式中最简单的一种实现方式.但是问题也比较明显.单例在 ...

随机推荐

  1. idea 打包java程序

    创建maven项目 在pom.xml中添加: <build> <plugins> <plugin> <groupId>org.apache.maven. ...

  2. 2017面向对象程序设计(Java)第三周学习总结

    白驹过隙,日月如梭,一转眼,我们已经度过了第三周的学习时光,随着时间的一天天流逝,我么对知识的积累也逐渐增多.当然,我们还有许许多多需要改进的地方.下面,我将对第三周的助教工作进行总结,望老师及同学们 ...

  3. T分布(T-Distribution)

    1.What is the T Distribution? T分布(也叫Student 's T分布)是一组与正态分布曲线几乎相同的分布,只是更短更胖一点.当有小样本时,使用t分布而不是正态分布.样本 ...

  4. 第五章 二叉树(e5)重构

  5. .net调用web邮箱发送邮件(转载)

    public static void SendEmail() { System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient( ...

  6. [leetcode]283. Move Zeroes移零

    Given an array nums, write a function to move all 0's to the end of it while maintaining the relativ ...

  7. 绑定服务-----------binderService TimerTask的使用

    绑定服务 服务中通过定义Binder对象的子类让这个子类成为桥梁   在onBind()中返回子类对象 这样就可以在activity中调用这个子类的方法 在Activity中通过ServiceConn ...

  8. DataTableExtensions

    public static class DataTableExtensions { public static List<dynamic> ToDynamic(this DataTable ...

  9. super限定,子类中系统查找变量的顺序:

    示例代码如下: import static java.lang.System.*; //-父类: class BaseClass{ public int a=7; } //-子类: public cl ...

  10. 学美工、平面设计、UI设计,哪个有前途?

    首先,在分析学美工.平面设计.UI设计,哪一个更有前途的时候,先要对三类设计有一个大概的了解. 比如“学美工.平面设计.UI设计是什么”等知识,才能更好地去进行选择. 01 阐述美工.平面设计.UI设 ...