前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式之单例设计模式

设计模式之单例设计模式

原创
作者头像
用户7245046
发布2023-02-17 19:30:30
3440
发布2023-02-17 19:30:30
举报
文章被收录于专栏:设计模式ychen设计模式ychen
  • 单例的实现

代码语言:txt
复制
- 懒汉式
    - 线程不安全
    - 线程安全
- 饿汉式
- DCL(双重校验锁)
- 登记式/静态内部类

单例设计模式:

1.保证一个类只有一个实例 (控制某些共享资源的访问权限 如 数据库或文件)

2.为该实例提供一个全局访问节点

实现步骤:

1.将默认构造方法设置为私有,防止其他对象使用单例类 new运算符

2.新建一个静态构建方法作为构造函数,该函数自动调用私有构造函数来创建对象,并将其保存在一个静态成员变量中。此后 所有对于该函数的调用都将返回这一缓存对象

懒汉式(线程不安全)

public class Singleton {

代码语言:txt
复制
`private static Singleton instance;`  
代码语言:txt
复制
`private Singleton (){}`  
代码语言:txt
复制
`public static Singleton getInstance() {`  
代码语言:txt
复制
    `if (instance == null) {`  
代码语言:txt
复制
        `instance = new Singleton();`  
代码语言:txt
复制
    `}`  
代码语言:txt
复制
    `return instance;`  
代码语言:txt
复制
`}`  

}

懒汉式(线程安全) 说真正用到它的时候才去创建实例 synchronized锁的粒度太大

public class Singleton {

代码语言:txt
复制
`private static Singleton instance;`  
代码语言:txt
复制
`private Singleton (){}`  
代码语言:txt
复制
`public static synchronized Singleton getInstance() {`  
代码语言:txt
复制
    `if (instance == null) {`  
代码语言:txt
复制
        `instance = new Singleton();`  
代码语言:txt
复制
    `}`  
代码语言:txt
复制
    `return instance;`  
代码语言:txt
复制
`}`  

三、饿汉式(程序刚启动时就创建了实例)

public class Singleton {

代码语言:txt
复制
private static Singleton instance = new Singleton();  
代码语言:txt
复制
private Singleton (){}  
代码语言:txt
复制
public static Singleton getInstance() {  
代码语言:txt
复制
   return instance;  
代码语言:txt
复制
}  

}

四、DCL(双重校验锁)

public class Singleton {

private static Singleton singleton = null;

private Singleton(){}

public static Singleton getInstance(){

/*

一堆业务处理代码

*/

if(null == singleton){

synchronized(Singleton.class){//锁粒度变小

if(null == singleton){//DCL

try {

Thread.sleep(1);

} catch (InterruptedException e) {

e.printStackTrace();

}

singleton = new Singleton();

}

}

}

return singleton;

}

public static void main(String[] args) {

for (int i=0;i<1000;i++){

new Thread(()-> System.out.println(Singleton.getInstance().hashCode())).start();

}

}

}

通过在第10行又加了一层if判断,也就是所谓的Double Check Lock。也就是说即便拿到锁了,也得去作一步判断,如果这时判断对像不为空,那么就不用再创建对象,直接返回就可以了,很好的解决了“改进2”中的问题。但这里第8行是不是可以去了,我个人觉得都行,保留第8行的话,是为了提升效率,因为如果去了,每个线程过来就直接抢锁,抢锁本身就会影响效率,而if判断就几ns,且大部分线程是不需要抢锁的,所以最好保留。 到这DCL 单例的原理就介绍完了,但是还是有一个问题。就是需要考虑指令重排序的问题,因此得加入volatile来禁止指令重排序。继续分析代码,为了分析方便这里将Singleton代码简化

---

单例模式使用DCL(双重检验锁的)的原理:

单例模式 有饿汉式和懒汉式,

饿汉式在程序刚启动就创建实例,虽然线程安全,但是比较浪费资源, 懒汉式在 在需要的时候才会去创建实例,但是在多线程并发的情况下存在线程不安全的问题,

优化1:是加synchronize关键字,但是synchronize关键字直接加在放上下粒度太大。

优化2:使用 synchronize(Singleton.class){try{}catch()} 来减少锁的粒度,但是并发就会又存在问题 当线程1在准备抢锁的时候可能会被阻塞(如时间片到),这时候线程二 上cpu运行,顺利拿到锁并结束运行释放锁。线程1 恢复,拿到锁吗,运行结束。造成了的线程不安全.

优化3: 尽管某一个线程抢到了锁,也要判断当前 是否已存在实例化的对象,存在了就不在创建,不存在在去实例化。 优化4:就是需要考虑指令重排序的问题,因此得加入volatile来禁止指令重排序

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com