设计模式【synchronize+volatile双重检查机制的懒汉式单例】
前言
上文提到了两种懒汉式单例加载问题,针对多线程我提出了一种加锁的方式避免重复实例化。本来以为就解决了问题。虽然测试中我没有发现问题,但是请教了一个老前辈他给我指出了其中的不足。
问题分析
加锁就是让获取对象时能够线性执行。但是因为我们锁是加载if上的。
当A线程获取锁成功时,并且完成了对象的创建后,B线程中对象并没有及时的得到刷新,这个时候B线程也获取到A线程释放的锁了,那么还是会重复创建对象。
这部分就涉及到线程对象都是拷贝在每个线程中的。前辈还说没有遇到问题是因为我运气好。实际上还是存在一定的安全隐患的。
解决方案
其实遇到问题是好事,只有遇到问题才能说明我们有进步的空间,更确切的说我们有进步的机会。如果我们贪图安逸那么只会错失高峰。
上面的问题其实涉及到一个知识点就是Java中线程中对象时如何刷新的。真实对象时在内存中线程中都是在内存中拷贝的一个副本。线程修改对象实际上是修改副本然后回传内存。内存中在分发给各个线程。这个过程就是我们上述的原因出现。
volatile关键字就能很好的解决,他能够做到当内存变量出现改变时第一时间刷新最新值。
volatile private static Person person = null; private SingleFactory() { } public static Person getIstance() { try { Thread.sleep(30); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } synchronized (SingleFactory.class) { if (person == null) { person = new Person(); } } return person; }复制代码
总结
一个简单的单例模式我居然能够学到synchronize和volatile两个关键字,简直赚了;关于这两个关键字设计到计算机底层原理,这里我们就不在深入研究了
作者:本该努力的年龄千万别放弃
链接:https://juejin.cn/post/7020606115373121567