单例模式和双重检测的小结-阿里云开发者社区

开发者社区> shy丶gril> 正文

单例模式和双重检测的小结

简介:
+关注继续查看

设计模式的经典模式之一——单例模式

这个也是面试经常被问起的面试,一般都要求手写

【饿汉模式】非延时加载 ——以空间换时间

懒汉模式】延时加载——以时间换空间

看似简单,但是在懒汉模式还隐藏了一个双重检测,其中还是涉及到JVM内存的“无序写入”问题(后面使用的 volatile )


1、饿汉模式

比较简单,非延时加载,一上来就把对象给new出来了

[java] view plain copy
  1. <span style="font-family:Microsoft YaHei;font-size:14px;">public class Singleton {  
  2.     private Singleton(){} //默认构造器  
  3.     private static Singleton instance = new Singleton();//直接加载  
  4.     public Singleton getIntance(){  
  5.         return instance;  
  6.     }  
  7. }</span>  

2、懒汉模式,延时加载

【1】普通

[java] view plain copy
  1. <span style="font-family:Microsoft YaHei;font-size:14px;">public class Singleton {  
  2.     private Singleton() { } // 默认构造器  
  3.   
  4.     private static Singleton instance = null;// 延时加载  
  5.     //每次运行都要创建实例因而需要加锁保护  
  6.     public static synchronized Singleton getIntance() {  
  7.         if (instance == null) {  
  8.             instance = new Singleton();// 判断之后加载  
  9.         }  
  10.         return instance;  
  11.     }  
  12.   
  13. }</span>  



【2】双重检测(有缺陷来自JVM自身)

上面尽管这样做到了线程安全,并且解决了多实例问题,但并不高效。在任何调用这个方法的时候,你都需要承受同步带来的性能开销,然而同步只在第一次调用的时候才被需要,也就是单例类实例创建的时候。这将促使我们使用双重检查锁模式(double checked locking pattern),一种只在临界区代码加锁的方法。一般称其为双重检查锁,因为会有两次检查 _instance == null,一次不加锁,另一次在同步块上加锁。

[java] view plain copy
  1. <span style="font-family:Microsoft YaHei;font-size:14px;">public class Singleton {  
  2.     private Singleton() { } // 默认构造器  
  3.   
  4.     private volatile static Singleton instance = null;// volatile 可见性/防止重排序  
  5.   
  6.     public static Singleton getIntance() {  
  7.         // 第一重判断  
  8.         if (instance == null) {  
  9.             // 锁定代码块  
  10.             synchronized (Singleton.class) {  
  11.                 // 第二重判断  
  12.                 if (instance == null) {  
  13.                     instance = new Singleton();// 判断之后加载  
  14.                 }  
  15.   
  16.             }  
  17.   
  18.         }  
  19.         return instance;  
  20.     }  
  21.   
  22. }</span>  
如果使用双重检查锁定来实现懒汉式单例类,需要在静态成员变量instance之前增加修饰符volatile(可见性,防止重排序),被volatile修饰的成员变量可以确保多个线程都能够正确处理,且该代码只能在JDK 1.5及以上版本中才能正确执行。

【3】ThreadLocal模式的单例

[java] view plain copy
  1. <span style="font-family:Microsoft YaHei;font-size:14px;">    public class Singleton{    
  2.       public static final ThreadLocal  threadInstance=new ThreadLocal();    
  3.      public static Singleton singleton=null;    
  4.       public static getSingleton(){    
  5.          if(threadInstance.get()==null){    
  6.              createSingleton();    
  7.           }    
  8.       }    
  9.       public static Singleton createSingleton(){    
  10.          synchronized(Singleton.class){    
  11.            if(singleton==null){    
  12.                 singleton=new Singleton();    
  13.             }    
  14.           }    
  15.       }    
  16.         
  17.     }   </span>  

ThreadLocal的全局变量局部化 第一次检测采用线程局部来做如果线程已经访问过则不需要进入同步块


转载:http://blog.csdn.net/xsf50717/article/details/47305203

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
设计模式:单例模式的写法(基础写法和线程安全写法)
单例模式的写法很多,先给出一种最基础的写法: (A种写法): package singleton; public class SingletonInstance { private static SingletonInstance mSingletonInstance = null; // 特意将构造函数设置成 private,防止外部使用者new SingletonInstance()。
720 0
线程安全的单例模式
面试的时候,常常会被问到这样一个问题:请您写出一个单例模式(Singleton Pattern)吧。好吧,写就写,这还不容易。顺手写一个: public final class EagerSingleton   {       private static EagerSingleton sing...
743 0
单例模式在生产环境jedis集群中的应用
背景:不久前单位上线一款应用,上了生产环境之后,没过多久,便吃掉了服务器所有的内存,最后导致网站服务挂了。   在解决了这一问题之后,我发现这其实是典型的一单例模式,现分享一下。 之前存在问题的老代码如下: 这是导致问题所在的那个关键方法 public synchronized sta...
1205 0
双重检查锁单例模式为什么要用volatile关键字?
双重检查锁单例模式为什么要用volatile关键字?
1214 0
C#设计模式学习笔记-单例模式
本文转载:http://www.cnblogs.com/xun126/archive/2011/03/09/1970807.html最近在学设计模式,学到创建型模式的时候,碰到单例模式(或叫单件模式),现在整理一下笔记。
850 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
10500 0
ElasticSearch java api -单例模式
//单例模式 private static Settings getSettingInstance(){ if(settings==null){ synchronized (Settings.class) { if(settings==null){ settings = ImmutableSettings.
817 0
c# 设计模式之单例模式学习
c#的设计模式有很多种,当然也可以说语言的设计模式有很多种(23种),单例模式应该是其中最简单的一种,但是不要因为简单而小看他,否则最后后悔的肯定是你 单例模式包括懒汉模式(还有多线程下的锁定)、恶汉模式 下面写一下饿汉模式的实现原理:  public Class Singleton { ...
928 0
+关注
1878
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载