diff --git a/pom.xml b/pom.xml
index 504974e..ad04c1e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -90,6 +90,11 @@
cglib
3.3.0
+
+ org.projectlombok
+ lombok
+ 1.18.10
+
diff --git a/src/main/com/mxy/design/singleton/dcl/Singleton.java b/src/main/com/mxy/design/singleton/dcl/Singleton.java
index e322be4..4a5dc1b 100644
--- a/src/main/com/mxy/design/singleton/dcl/Singleton.java
+++ b/src/main/com/mxy/design/singleton/dcl/Singleton.java
@@ -1,20 +1,36 @@
package com.mxy.design.singleton.dcl;
+import lombok.SneakyThrows;
+
/**
* DCL模式
*/
public class Singleton {
- //重点:volatile 增加线程间的可见性 线程安全
+ /*
+ 重点:volatile 利用有序性保证变量不参与重排序
+ synchronized 保证代码块里面有序性,不能保证未进入代码块的变量有序,jvm依然可以重排序
+ dcl问题点:
+ 需要知道的是 singleton = new Singleton();这句代码并不是一个原子操作,他的操作大体上可以被拆分为三步
+ 1.分配内存空间
+ 2.实例化对象instance
+ 3.把instance引用指向已分配的内存空间,此时instance有了内存地址,不再为null了
+ java是允许对指令进行重排序, 那么以上的三步的执行顺序就有可能是1-3-2. 在这种情况下,
+ 如果线程A执行完1-3之后被阻塞了, 而恰好此时线程B进来了 此时的 singleton 已经不为空了所以线程B走完代码
+ 在[第一步]以后就直接返回了这个还没有实例化好的instance, 所以在调用其后续的实例方法时就会得不到预期的结果
+ */
private static volatile Singleton singleton;
- private Singleton() {}
+ private Singleton() {
+ }
+ @SneakyThrows
public static Singleton getInstance() {
- if (singleton == null) {
+ if (singleton == null) { //第一步,这一行在临界区,不受锁保护
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
+ //同步代码块的unlock之前会把线程中的最新状态刷回主存
}
}
return singleton;
diff --git a/src/test/com/mxy/design/singleton/SingletonTest.java b/src/test/com/mxy/design/singleton/SingletonTest.java
index 6493e57..9189fda 100644
--- a/src/test/com/mxy/design/singleton/SingletonTest.java
+++ b/src/test/com/mxy/design/singleton/SingletonTest.java
@@ -1,11 +1,11 @@
package com.mxy.design.singleton;
import com.mxy.design.singleton.enum_.Singleton;
+import lombok.SneakyThrows;
import org.junit.Test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
/**
* 单利模式:单例对象的类只能允许一个实例存在。
@@ -25,7 +25,7 @@ public class SingletonTest {
@Test
public void logicTest1() {
- for (int i = 0; i <10 ; i++) {
+ for (int i = 0; i < 10; i++) {
System.out.println(com.mxy.design.singleton.lazy.Singleton.getInstance());
}
System.out.println("懒汉模式");
@@ -33,7 +33,7 @@ public void logicTest1() {
@Test
public void logicTest2() {
- for (int i = 0; i <10 ; i++) {
+ for (int i = 0; i < 10; i++) {
System.out.println(com.mxy.design.singleton.hungry.Singleton.getInstance());
}
System.out.println("饿汉模式");
@@ -59,7 +59,7 @@ public void logicTest4() {
threadPool.execute(new Runnable() {
@Override
public void run() {
- System.out.println(com.mxy.design.singleton.dcl.Singleton.getInstance());
+ System.out.println(com.mxy.design.singleton.dcl.Singleton.getInstance().hashCode());
}
});
}
@@ -95,14 +95,11 @@ public void run() {
System.out.println("静态内部类模式");
}
+ @SneakyThrows
private void shutDownThreadPool() {
threadPool.shutdown();
- try {
- if (!threadPool.awaitTermination(5, TimeUnit.SECONDS)) {
- threadPool.shutdownNow();
- }
- } catch (InterruptedException e) {
- threadPool.shutdownNow();
+ while (!threadPool.isTerminated()) {
+ Thread.sleep(100);
}
}