By
木子雷
阅读数: 次
前言:
在本文中会使用代码进行展示懒汉单例模式为什么需要进行二次判空;代码中使用到 CountDownLatch 倒计时器,不清楚CountDownLatch 使用的请参考此文“倒计时器:CountDownLatch” 。
代码展示:
1、懒汉式单例模式类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| public class Singleton { private static volatile Singleton sin = null; public static int i = 0; public static int j = 0; private Singleton() { }; public static Singleton getInstance() { if (sin == null) { synchronized (Singleton.class) { i++; if (sin == null) { sin = new Singleton(); j++; } } } return sin; } }
|
2、多线程并发调用单例模式的测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| public class ThreadTest implements Runnable { static final CountDownLatch latch = new CountDownLatch(10); static final ThreadTest demo = new ThreadTest(); @Override public void run() { try { Singleton.getInstance(); System.out.println(Thread.currentThread().getName()); } catch (Exception e) { e.printStackTrace(); } finally { latch.countDown(); } } public static void main(String[] args) throws InterruptedException { ExecutorService exec = Executors.newFixedThreadPool(10); for (int i=0; i<10; i++){ exec.submit(demo); } latch.await(); System.out.println("共有 ( " + Singleton.i + " ) 个线程获取到对象锁"); System.out.println("最终生成了( " + Singleton.j + " )个Singleton实例对象"); exec.shutdown(); } }
|
运行上面的mian方法,会得到以下的一种输出结果(存在多种输出结果)
1 2 3 4 5 6 7 8 9 10 11 12
| pool-1-thread-1 pool-1-thread-7 pool-1-thread-5 pool-1-thread-3 pool-1-thread-6 pool-1-thread-2 pool-1-thread-4 pool-1-thread-9 pool-1-thread-8 pool-1-thread-10 共有 ( 2 ) 个线程获取到对象锁 最终生成了( 1 )个Singleton实例对象
|
总结:
从运行结果可以看出,如果不进行第二次判空的话,那么在竟锁池(锁池)中如果还有活跃的线程在等待获取的锁的话,在锁释放后就会再次竞争获取锁,获取的锁的线程进入”就绪状态”,当cpu分配其”时间片”后进行线程的调度,从而线程进入”运行中状态”,并会去执行同步的代码块,如果在没加如二次判空的话,就会导致系统中存在多个实例,而在进行判空后,即使你获取到了锁,但在执行同步代码块时也会直接跳过。
竟锁池(锁池)的概念:Java中的锁池和等待池
❤不要忘记留下你学习的足迹 [点赞 + 收藏 + 评论]嘿嘿ヾ
一切看文章不点赞都是“耍流氓”,嘿嘿ヾ(◍°∇°◍)ノ゙!开个玩笑,动一动你的小手,点赞就完事了,你每个人出一份力量(点赞 + 评论)就会让更多的学习者加入进来!非常感谢! ̄ω ̄=