Skip to content

Commit aadd3cc

Browse files
Update 设计模式.md
1 parent 36a3c40 commit aadd3cc

File tree

1 file changed

+40
-0
lines changed

1 file changed

+40
-0
lines changed

设计模式.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,43 @@ func main() {
8080
}
8181
```
8282

83+
84+
85+
```java
86+
public class DoubleCheckedLock {
87+
88+
// 使用volatile修饰禁止重排序
89+
private volatile static DoubleCheckedLock instance;
90+
91+
private DoubleCheckedLock() {
92+
//构造器必须私有 不然直接new就可以创建
93+
}
94+
95+
96+
public static DoubleCheckedLock getInstance() {
97+
//第一次判断,假设会有好多线程,如果doubleLock没有被实例化,那么就会到下一步获取锁,只有一个能获取到,
98+
//如果已经实例化,那么直接返回了,减少除了初始化时之外的所有锁获取等待过程
99+
if (instance == null) {
100+
//同步
101+
synchronized (DoubleCheckedLock.class) {
102+
//第二次判断是因为假设有两个线程A、B,两个同时通过了第一个if,然后A获取了锁,进入然后判断doubleLock是null,
103+
// 他就实例化了doubleLock,然后他出了锁,这时候线程B经过等待A释放的锁,B获取锁了,
104+
// 如果没有第二个判断,那么他还是会去new DoubleLock(),再创建一个实例,所以为了防止这种情况,需要第二次判断
105+
if (instance == null) {
106+
//下面这句代码其实分为三步:
107+
//1.开辟内存分配给这个对象
108+
//2.初始化对象
109+
//3.将内存地址赋给虚拟机栈内存中的doubleLock变量
110+
//注意上面这三步,第2步和第3步的顺序是随机的,这是计算机指令重排序的问题
111+
//假设有两个线程,其中一个线程执行下面这行代码,如果第三步先执行了,就会把没有初始化的内存赋值给doubleLock
112+
//然后恰好这时候有另一个线程执行了第一个判断if(doubleLock == null),然后就会发现doubleLock指向了一个内存地址
113+
//这另一个线程就直接返回了这个没有初始化的内存,所以要防止第2步和第3步重排序
114+
instance = new DoubleCheckedLock();
115+
}
116+
}
117+
}
118+
return instance;
119+
}
120+
}
121+
```
122+

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy