简述:本周在闲暇之余看了下重新看了单例模式,发现有很多以前不懂的地方,故梳理了下,和大家分享。
1,相关链接
https://www.cnblogs.com/dolphin0520/p/3920373.html;
https://blog.csdn.net/chenchaofuck1/article/details/51702129;
https://blog.csdn.net/dl88250/article/details/5439024;
https://blog.csdn.net/qweasdzxc456123/article/details/72722515;
https://blog.csdn.net/zjhwqx/article/details/72912024;
以上是我在单例模式学习中相关知识点查找的相关链接,写的都蛮详细的,我以下就是对这些内容的一点简单的个人复习,你可以完全不看我下面的内容。
2,单例模式
private static volatile Singleton instance=null;
private Singleton() {
}
if(instance==null) {
synchronized (Singleton.class) {
if(instance==null) {
instance=new Singleton();
}
}
}return instance;
}
volatile,
java5之前就出现,但在java5出现后才能正常使用,原因在于编译java5之前对于该字段没有做较多的编译顺序处理,导致多线程下不安全;
多线程下涉及主存-缓存概念,先进主存,然后进缓存,由缓存一致性协议同步数据,每个线程在缓存中具体操作,并将结果反馈给主存,多线程有三个概念:原子性问题,可见性问题,有序性问题:
原子性可以简单理解成完整性,要么全部执行完成,要么不执行;
可见性指一个线程对变量的修改变化,对于别的线程都是可及时获知的;
有序性指即程序执行的顺序按照代码的先后顺序执行,这里是有一个背景,程序在运行前会先被jvm编译优化,然后编译成机械码,这两个过程都不能保证完全按原有顺序,称为指令重排序,现在的jvm已经预设了一些编译顺序的规则,volatile的编译规则就是在java5完善的。
volatile的主要作用是在线程a修改完变量数据后,马上更新到主存中。它保证了可见性、有序性,但是不能保证原子性,结合采用synchronized或lock或AtomicInteger(不一定完全适用所有场景),能帮忙实现原子性;
双重检查锁定
单线程下只需一个null判断就可以了,但在多线程下,需要在synchronized内外都加null判断,以保证第一个以外线程不会创建对象;
双重检查锁定也会遇到编译问题,但在java5以后可以结合volatile,保证线程安全。
其他
其实还有别的扩展的地方,像具体的内存模型,二级和三级缓存,设计模式原则等等,牵扯太多也太广泛,可以自行学习。
最后感谢上述连接中大神的详细描述。