1    课程讲解

1.1  为何要使用双重检查

1.2  双重检查的缺点

1.3  指令重排序讲解

1.4  指令重排序比喻(自己理解)

1.5  如何解决指令重排序问题

2    代码演练

2.1  代码演练1(双重检查  解决对象锁和类锁的问题)

2.2  代码演练2(volatile 应用:解决重排序问题)

1    课程讲解
1.1  为何要使用双重检查

在上节课的时候,多线程的时候,由于一个线程被锁,其他的线程无法访问该类,被堵塞。性能大大降低,双重检查主要是应用解决此类问题。

双重检查可以使更多的线程堵塞在方法中,而不是在类之外,这样的话,当锁被释放的时候,能够更快的执行,可以大大的提高效率。

1.2  双重检查的缺点

java在执行过程中,可能会出现指令重排序问题,(后边语句参考本节2.1代码演练2)导致a线程(先来的)的对象已经赋值,但是还没有初始化完成,这时线程b(后到的)经过判断,也开始访问对象(因为现在对象不为空),导致线程b访问的是线程a还未初始化完成的对象。由于对象并没有被完整的初始化上,系统会报异常。

1.3  指令重排序讲解

初始化的时候,实际进行了三个步骤:

a  给该对象分配内存

b  初始化该对象

c  设置该对象指向给该对象分配的内存

一般情况下,按照abc的顺序执行,但是也会有一定几率bc 颠倒。

这在单线程中执行的时候并没有问题,而且能够提高运行的效率。

1.4  指令重排序比喻(自己理解)

可以比喻如下:

人们来吃饭,

a  首先食堂拿出一份饭,

b  确定这个人是谁,

c  这个人拿走这份饭

1.5  如何解决指令重排序问题

两种方法:

a  使重排序不再发生,每个执行的进程都按照初始化的正常步骤进行 参见  本节代码2.2

b  不允许后来的线程 看到 先来的线程进行的重排序问题

2    代码演练
2.1  代码演练1(解决对象锁和类锁的问题)

测试类:

  1. package com.geely.design.pattern.creational.singleton;
  2.  
  3. public class Test {
  4.  
  5. /*public static void main(String [] args){
  6. //这样写异常,因为构造方法私有
  7. // LazySingleton lazySingleton = new LazySingleton();
  8. LazySingleton lazySingleton = LazySingleton.getInstance();
  9. System.out.println(lazySingleton);
  10. }*/
  11.  
  12. public static void main(String [] args){
  13. Thread thread1 = new Thread(new T());
  14. Thread thread2 = new Thread(new T());
  15. thread1.start();
  16. thread2.start();
  17. System.out.println("结束了!!!");
  18. }
  19. }

线程类:

  1. package com.geely.design.pattern.creational.singleton;
  2.  
  3. /**
  4. * 注:该类为线程类,调用LazySingleton
  5. */
  6. public class T implements Runnable{
  7.  
  8. /*@Override
  9. public void run() {
  10. LazySingleton lazySingleton = LazySingleton.getInstance();
  11. System.out.println(Thread.currentThread().getName()+"==="+lazySingleton);
  12.  
  13. }*/
  14.  
  15. @Override
  16. public void run() {
  17. LazyDoubleCheckSingleton lazyDoubleCheckSingleton = LazyDoubleCheckSingleton.getInstance();
  18. System.out.println(Thread.currentThread().getName()+"==="+lazyDoubleCheckSingleton);
  19. }
  20. }

实体类:

  1. package com.geely.design.pattern.creational.singleton;
  2.  
  3. public class LazyDoubleCheckSingleton {
  4. /*
  5. 属性私有,其他外部类,无法调用该属性,安全
  6. */
  7. private static LazyDoubleCheckSingleton lazyDoubleCheckSingleton = null;
  8.  
  9. /**
  10. * 构造方法私有,其他类无法实例化该类
  11. */
  12. private LazyDoubleCheckSingleton(){
  13. }
  14.  
  15. /**
  16. * 换一种写法,
  17. *
  18. * @return
  19. */
  20. public static LazyDoubleCheckSingleton getInstance(){
  21. if(lazyDoubleCheckSingleton == null){
  22. synchronized (LazyDoubleCheckSingleton.class){
  23. if(lazyDoubleCheckSingleton == null){
  24. lazyDoubleCheckSingleton = new LazyDoubleCheckSingleton();
  25. }
  26. }
  27. }
  28. return lazyDoubleCheckSingleton;
  29. }
  30.  
  31. }

打印结果:

  1. "C:\Program Files\Java\jdk1.7.0_79\bin\java.exe" -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:9096,suspend=y,server=n -javaagent:C:\Users\weijingli\.IdeaIC2018.1\system\captureAgent\debugger-agent.jar=file:/C:/Users/weijingli/AppData/Local/Temp/capture.props -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.7.0_79\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jce.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jfxrt.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\resources.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\rt.jar;F:\xiangmu3\Xin\Idea\design_pattern\target\classes;D:\java\devolopKit\idea\anZh\IntelliJ IDEA Community Edition 2018.1.4\lib\idea_rt.jar" com.geely.design.pattern.creational.singleton.Test
  2. Connected to the target VM, address: '127.0.0.1:9096', transport: 'socket'
  3. 结束了!!!
  4. Thread-0===com.geely.design.pattern.creational.singleton.LazyDoubleCheckSingleton@8fea539
  5. Disconnected from the target VM, address: '127.0.0.1:9096', transport: 'socket'
  6. Thread-1===com.geely.design.pattern.creational.singleton.LazyDoubleCheckSingleton@8fea539
  7.  
  8. Process finished with exit code 0
2.2  代码演练2(volatile 应用:解决重排序问题)

java语言规范中规定:所有线程执行java程序时,必须要遵守intra-thread semantics

intra-thread semantics 保证重排序不会改变单线程内的程序执行结果。

换句话说,intra-thread semantics 允许那些在单线程内,不会改变单线程程序执行结果的重排序。

  1. package com.geely.design.pattern.creational.singleton;
  2.  
  3. public class LazyDoubleCheckSingleton {
  4. /*
  5. 1 volatile关键字的作用
  6. 将当前处理器缓存行的数据写回到内存,该操作会使在其他cpu内存中缓存了该内存地址的数据无效。它们又从共享内存同步数据。 如此操作保存内存的可见性。j
  7. 2
  8. */
  9. private volatile static LazyDoubleCheckSingleton lazyDoubleCheckSingleton = null;
  10.  
  11. /**
  12. * 构造方法私有,其他类无法实例化该类
  13. */
  14. private LazyDoubleCheckSingleton(){
  15. }
  16.  
  17. /**
  18. * 换一种写法,
  19. *
  20. * @return
  21. */
  22. public static LazyDoubleCheckSingleton getInstance(){
  23. if(lazyDoubleCheckSingleton == null){
  24. synchronized (LazyDoubleCheckSingleton.class){
  25. if(lazyDoubleCheckSingleton == null){
  26. lazyDoubleCheckSingleton = new LazyDoubleCheckSingleton();
  27. }
  28. }
  29. }
  30. return lazyDoubleCheckSingleton;
  31. }
  32.  
  33. }

设计模式课程 设计模式精讲 8-3 单例设计模式-DoubleCheck双重检查实战及原理解析的更多相关文章

  1. JAVA_SE基础——38.单例设计模式

    本文继续介绍23种设计模式系列之单例模式. 我们在javaSE的基础学习中,会讲到:单例设计模式.模板设计模式.装饰者设计模式.观察者设计模式.工厂设计模式 我以后随着水平的提高,我会专门开个分类写设 ...

  2. 单例设计模式(Singleton)

    一.单例设计模式介绍 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例, 并且该类只提供一个取得其对象实例的方法(静态方法) 例如:Hibernate的Se ...

  3. Java设计模式—单例设计模式(Singleton Pattern)全然解析

    转载请注明出处:http://blog.csdn.net/dmk877/article/details/50311791 相信大家都知道设计模式,听的最多的也应该是单例设计模式,这种模式也是在开发中用 ...

  4. iOS开发之单例设计模式(完整正确版本)

    单例的意思从字面上就可以略知一二,所谓单例就是确保在程序运行过程中只创建一个对象实例.可以用于需要被多次广泛或者说多次使用的资源中,比如我们常见的网络请求类.工具类以及其它管理类等.比如我iOS开发中 ...

  5. JAVA之旅(十四)——静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制

    JAVA之旅(十四)--静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制 JAVA之旅,一路有你,加油! 一.静态同步函数的锁是clas ...

  6. JAVA之旅(六)——单例设计模式,继承extends,聚集关系,子父类变量关系,super,覆盖

    JAVA之旅(六)--单例设计模式,继承extends,聚集关系,子父类变量关系,super,覆盖 java也越来越深入了,大家加油吧!咱们一步步来 一.单例设计模式 什么是设计模式? JAVA当中有 ...

  7. 【java】设计模式-单例设计模式

    单例设计模式:解决一个类在内存中是存在一个对象的问题.当需要该事物的对象在内存中唯一时,将以下三步添加即可. 思想:想要保证对象唯一1.为了避免其他程序过多的建立该类对象,先禁止其他程序建立该类对象2 ...

  8. 【iOS 单例设计模式】底层解析与运用

    [iOS 单例设计模式]底层解析与运用 一.单例设计名词解释: (官方解释)单例模式确保一个类只有一个实例,自行提供这个实例并向整个系统提供这个实例.(形象比喻)程序 — 公司   单例实例 - 管理 ...

  9. 单例设计模式全局缓存accessToken

    使用微信JS-SDK开发的小伙伴们,看文档经常会看到这样一句话:(下面是微信开发文档的一部分原话截图) 这句话就是:开发者必须在自己的服务全局缓存access_token,jsapi_ticket 下 ...

随机推荐

  1. html学习-第一集(基本标签)

    什么是HTML html是一套规则,浏览器认识的规则 开发者怎么使用html 学习HTML语言 开发后台程序 写HTML文件 从数据库获取数据,然后替换到html中对应的位子(web框架) HTML文 ...

  2. gRPC Learning Notes

    简介 更多内容参考:https://www.grpc.io/docs/guides/ gRPC 是一个高性能.开源和通用的 RPC 框架,面向移动和 HTTP/2 设计.目前提供 C.Java 和 G ...

  3. 极简的js点击组图切换效果

    程序员进行前端开发时,时常要用到点击切换组图的动画效果,网上确实有很多此类插件,但是都很麻烦,乌糟糟无数代码,有那个看的时间,自己都能把功能写完了.在这里我提供一段极简的js点击组图切换效果代码,包含 ...

  4. Spring Security 源码分析 --- WebSecurity

    概述 spring security 源码分析系列文章. 源码分析 我们想一下,我们使用 ss 框架的步骤是怎么样的. @Configuration @EnableWebSecurity @Enabl ...

  5. SpringCloud全家桶学习之概览(一)

    一.概览 根据百度百科的描述,微服务架构是一项在云中部署应用和服务的新技术.而SpringCloud是微服务架构思想的一个具体实现,它为开发人员提供了构建分布式系统中一些常见模式的工具(服务注册与发现 ...

  6. list的使用-Hdu 1276

    士兵队列训练问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Su ...

  7. ubuntu mysql允许root用户远程登录

    有两种方法: 一. 1.mysql>GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '123456' WITH GRANT OPT ...

  8. ZOJ4104 Sequence in the Pocket(2019浙江省赛)

    思维~ #include<bits/stdc++.h> using namespace std; ; int a[maxn]; int b[maxn]; int N; int main ( ...

  9. linux--网络管理-ifconfig,route,netstat,ip,ss,dns,主机名网卡名修改bond

    cat /etc/services 查看常见端口对应的服务 查一查某个端口号,是哪个进程在用  lsof  -i :6010 49152-65535:动态端口或私有端口,客户端程序随机使用的端口  其 ...

  10. jsp格式化日期

    1.先引入JSTL库 <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> ...