# 单例模式

## 定义

保证某个类在全局只有一个实例存在。

## 代码实现

### 饿汉模式

```
class Singleton {
    private static Singleton sInstance = new Singleton();

    //私有构造方法
    private Singleton() {
        
    }

    public static Singleton getInstance() {
        return sInstance;
    }
}
```

借助类加载机制避免了多线程重复创建实例问题，类加载时就进行初始化，没有实现懒加载。

### 懒汉模式（线程不安全）

```
class Singleton {
    private static Singleton sInstance;

    //私有构造方法
    private Singleton() {
        
    }

    public static Singleton getInstance() {
        if (sInstance == null) {
            //多个线程进入判断会创建不同的实例
            sInstance = new Singleton();
        }
        return sInstance;
    }
}
```

实现了延迟初始化，但是多线程访问会重复创建实例。

### 懒汉模式（互斥锁）

```
class Singleton {
    private static Singleton sInstance;

    //私有构造方法
    private Singleton() {
        
    }

    //使用 synchronized 保证互斥
    public static synchronized Singleton getInstance() {
        if (sInstance == null) {
            sInstance = new Singleton();
        }
        return sInstance;
    }
}
```

使用互斥锁避免的并发问题，但是由于每次获取实例都要加锁（大部分情况不需要这么做），导致性能较低。

### 懒汉模式（双重null检查）

```
class Singleton {
    private static volatile Singleton sInstance;

    // 私有构造方法
    private Singleton() {

    }

    public static Singleton getInstance() {
        if (sInstance == null) {
            //如果多个线程进入判断，通过加锁保证互斥
            synchronized (Singleton.class) {
                if (sInstance == null) {
                    sInstance = new Singleton();
                }
            }
        }
        return sInstance;
    }
}
```

既避免了并发问题，又避免了互斥锁写法带来的性能问题。

通过 volatile 关键字禁止指令重排和保证可见性。

### 静态内部类

```
class Singleton {
    // 私有构造方法
    private Singleton() {
    }

    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }

    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
}
```

只有调用getInstance()方法时才会加载静态内部类并创建静态常量，所以实现了延迟加载；通过类加载机制避免了多线程并发问题。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://wenhaiz.gitbook.io/kx-android/software_engineering/design_pattern/dan-li-mo-shi.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
