单例模式之我见
Posted Fable说
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单例模式之我见相关的知识,希望对你有一定的参考价值。
面试了十来个,问了单例没有一个满意的答案,尝试着写篇文章总结下。
单例模式在SDK开发中,非常重要,单例的目的:确保只有单个对象被创建;SDK唯一创建可以避免非常多的问题。示例代码,以java来写。
1.饿汉式
```java
public class Singleton {
//创建 Main 的一个对象
private static final Singleton instance = new Singleton();
//让构造函数为 private,这样该类就不会被实例化
private Singleton(){}
//获取唯一可用的对象
public static Singleton getInstance(){
return instance;
}
}
```
饿汉式关键点:
1)实例化对象,
2)构造函数声明为private,
3)获取这个类的对象,通过getInstance。
优点:
线程安全;实现简单。
缺点:
还没使用这个对象就创建了对象,浪费了资源。
2.懒汉式
```java
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
```
懒汉式,关键点:
1)当需要当时候才初始化;
2)synchronized是为了防止多线程调用时,线程不一致而加的;不加会出问题
优点:
线程安全。
缺点:
锁的粒度是一整块代码,粒度偏大。
3.双重校验锁 DCL,即 double-checked locking
```java
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
```
双重校验锁关键点:
1)if (singleton == null)判断了2次;如果第1次不写,多线程调用时,第2个线程调用时,还需要加锁一次,效率不高。
2)如果第2次不写,多线程调用时,会存在懒汉式一样的问题,线程不一致的问题
扩展:美团经典之问,DCL是否要加volatile?
volatile必须加,不加,指定重排,当对象有非初始化值时,如果发生了指令重排,这个对象的值是,初始值。
这个没法验证,当百万级高并发,会出现这个情况,而且你不知道问题出在哪。
优点:
线程安全。
缺点:
一不小心就踩坑。
以上是关于单例模式之我见的主要内容,如果未能解决你的问题,请参考以下文章