From c793370441cd0607142a51a8c362e41ae53fcbfc Mon Sep 17 00:00:00 2001 From: maxy19 <315802767@qq.com> Date: Wed, 1 Jan 2020 16:00:02 +0800 Subject: [PATCH] =?UTF-8?q?doc=EF=BC=9A=E5=A2=9E=E5=8A=A0=E4=B8=8E?= =?UTF-8?q?=E4=BF=AE=E6=94=B9dcl=E7=9B=B8=E5=85=B3=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 5 +++++ .../mxy/design/singleton/dcl/Singleton.java | 22 ++++++++++++++++--- .../mxy/design/singleton/SingletonTest.java | 17 ++++++-------- 3 files changed, 31 insertions(+), 13 deletions(-) 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); } }