auto commit
This commit is contained in:
parent
28491d402e
commit
5cea88d6fa
|
@ -739,9 +739,11 @@ MarinaraSauce
|
||||||
|
|
||||||
![](https://github.com/CyC2018/InterviewNotes/blob/master/pics//59aff6c1-8bc5-48e4-9e9c-082baeb2f274.jpg)
|
![](https://github.com/CyC2018/InterviewNotes/blob/master/pics//59aff6c1-8bc5-48e4-9e9c-082baeb2f274.jpg)
|
||||||
|
|
||||||
**3. 经典实现**
|
**3. 懒汉式-线程不安全**
|
||||||
|
|
||||||
以下实现中,私有静态变量被延迟化实例化,这样做的好处是,如果没有用到该类,那么就不会创建该私有静态变量,从而节约资源。这个实现在多线程环境下是不安全的,因为多个线程能够同时进入 if(uniqueInstance == null) 内的语句块,那么就会多次实例化 uniqueInstance 私有静态变量。
|
以下实现中,私有静态变量被延迟化实例化,这样做的好处是,如果没有用到该类,那么就不会创建私有静态变量,从而节约资源。
|
||||||
|
|
||||||
|
这个实现在多线程环境下是不安全的,如果多个线程能够同时进入 if(uniqueInstance == null) 内的语句块,那么就会多次实例化 uniqueInstance 私有静态变量。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class Singleton {
|
public class Singleton {
|
||||||
|
@ -760,9 +762,9 @@ public class Singleton {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**4. 线程不安全问题的解决方案一**
|
**4. 懒汉式-线程安全**
|
||||||
|
|
||||||
只需要对 getUniqueInstance() 方法加锁,就能让该方法一次只能一个线程访问,从而避免了对 uniqueInstance 变量进行多次实例化的问题。但是这样有一个问题是一次只能一个线程进入,性能上会有一定的浪费。
|
只需要对 getUniqueInstance() 方法加锁,那么在一个时间点只能有一个线程能够进入该方法,从而避免了对 uniqueInstance 进行多次实例化的问题。但是这样有一个问题,就是当一个线程进入该方法之后,其它线程视图进入该方法都必须等待,因此性能上有一定的损耗。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public static synchronized Singleton getUniqueInstance() {
|
public static synchronized Singleton getUniqueInstance() {
|
||||||
|
@ -773,17 +775,20 @@ public class Singleton {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**5. 线程不安全问题的解决方案二**
|
**5. 饿汉式-线程安全**
|
||||||
|
|
||||||
不用延迟实例化,采用直接实例化。
|
线程不安全问题主要是由于静态实例变量被初始化了多次,那么静态实例变量采用直接实例化就可以解决问题。但是直接初始化的方法也丢失了延迟初始化节约资源的优势。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
private static Singleton uniqueInstance = new Singleton();
|
private static Singleton uniqueInstance = new Singleton();
|
||||||
```
|
```
|
||||||
|
|
||||||
**6. 线程不安全问题的解决方案三**
|
**6. 双重校验锁-线程安全**
|
||||||
|
|
||||||
|
因为 uniqueInstance 只需要被初始化一次,之后就可以直接使用了。加锁操作只需要对初始化那部分的代码进行,也就是说,只有当 uniqueInstance 没有被初始化时,才需要进行加锁。
|
||||||
|
|
||||||
|
双重校验锁先判断 uniqueInstance 是否已经被初始化了,如果没有被初始化,那么才对初始化的语句进行加锁。如果只做一次判断,那么多个线程还是有可能同时进入实例化语句块的,因此需要仅此第二次的判断。
|
||||||
|
|
||||||
考虑第一个解决方案,它是直接对 getUniqueInstance() 方法进行加锁,而实际上只需要对 uniqueInstance = new Singleton(); 这条语句加锁即可。使用两个条件语句来判断 uniqueInstance 是否已经实例化,如果没有实例化才需要加锁。
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class Singleton {
|
public class Singleton {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user