关于单例的DCL方式分析
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方式分析的更多相关文章
- 关于java的volatile关键字与线程栈的内容以及单例的DCL
用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的最新的值.volatile很容易被误用,用来进行原子性操作. package com.guangshan.test; pub ...
- Swift中编写单例的正确方式
在之前的帖子里聊过状态管理有多痛苦,有时这是不可避免的.一个状态管理的例子大家都很熟悉,那就是单例.使用Swift时,有许多方法实现单例,这是个麻烦事,因为我们不知道哪个最合适.这里我们来回顾一下单例 ...
- Swift中的单例的实现方式
单例在iOS日常开发中是一个很常用的模式.对于希望在 app 的生命周期中只应该存在一个的对象,保证对象的唯一性的时候,一般都会使用单例来实现功能.在OC单例的写法如下: @implementatio ...
- 单例---被废弃的DCL双重检查加锁
被废弃的单例的DCL双重检查加锁/* *单例模式 *单例模式,保证一个类仅有一个实例,并提供一个访问它的全局访问点. *加同步锁的单例模式,适合在多线程中使用. */ class Singleton{ ...
- Redis 单例、主从模式、sentinel 以及集群的配置方式及优缺点对比(转)
摘要: redis作为一种NoSql数据库,其提供了一种高效的缓存方案,本文则主要对其单例,主从模式,sentinel以及集群的配置方式进行说明,对比其优缺点,阐述redis作为一种缓存框架的高可用性 ...
- Hi,我们再来聊一聊Java的单例吧(转)
1. 前言 单例(Singleton)应该是开发者们最熟悉的设计模式了,并且好像也是最容易实现的——基本上每个开发者都能够随手写出——但是,真的是这样吗? 作为一个Java开发者,也许你觉得自己对单例 ...
- Unity 游戏框架搭建 2018 (二) 单例的模板与最佳实践
Unity 游戏框架搭建 2018 (二) 单例的模板与最佳实践 背景 很多开发者或者有经验的老手都会建议尽量不要用单例模式,这是有原因的. 单例模式是设计模式中最简单的也是大家通常最先接触的一种设计 ...
- 探索Scala(3)-- 单例对象
研究一下Scala语言的单例对象(Singleton Objects),为下一篇文章做准备. static不是keyword 上一篇文章提到过,interface并非Scala语言keyword,能够 ...
- java单例五种实现模式梳理
java单例五种实现模式 饿汉式(线程安全,调用效率高,但是不能延时加载) 一上来就把单例对象创建出来了,要用的时候直接返回即可,这种可以说是单例模式中最简单的一种实现方式.但是问题也比较明显.单例在 ...
随机推荐
- STC-51开发板-单片机控制数码管&按键&点阵综合操作
操作: 实现按下一个按键,对应的数码管和点阵显示相应的数字 代码: /* *******************数码管按键综合项目********************* */ #include ...
- ionic2
拨打电话: <access origin="tel:*" launch-external="yes" /> 发邮件: <access orig ...
- mysql与redis的区别与联系
1.mysql是关系型数据库,主要用于存放持久化数据,将数据存储在硬盘中,读取速度较慢. redis是NOSQL,即非关系型数据库,也是缓存数据库,即将数据存储在缓存中,缓存的读取速度快,能够大大的提 ...
- tomcat 管理端 安全措施
由于公司的项目并未启用nginx负载均衡,所以自然也没用到tomcat与web应用一对一的安全操作,经常会遇到 重启单个应用又不想重启tomcat的情况.同时,又出于安全考虑,将tomcat的默认管理 ...
- zoj1649-Rescue (迷宫最短路径)【bfs 优先队列】
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=649 Rescue Time Limit: 2 Seconds Mem ...
- Codeforces Beta Round#2
Codeforces Beta Round#2 http://codeforces.com/contest/2 A 模拟题 #include<bits/stdc++.h> using na ...
- c++ stl常用
#include<iostream>#include<string>#include<vector>#include<list>#include< ...
- [leetcode]299. Bulls and Cows公牛和母牛
You are playing the following Bulls and Cows game with your friend: You write down a number and ask ...
- 20-java 对象链表空没空呢
写了一个 对象链表,往里面add了一些对象,最后我想看下链表是否为空,用 == null 为假,也看不出, 看下长度? 好吧, size() = 1: 打印 null , 那到底是不是空 啊, ...
- 文件Move操作
#coding=utf-8 import os import shutil stra = "G:/should/v3/a" strb = "G:/should/v3/b& ...