为什么单例要写成这种鬼样子

用过Struts2的同学应该会觉得我写的单例很熟悉。。嗯就是Struts里面的View的写法。。。

所以单例为什么要这么写。或者说volatile和synchronized关键字有什么作用

代码在单线程模式下执行顺序会看起来和代码的位置相同。无论是什么编程语言都会有这样的错觉这归功于现代CPU做了一系列的优化和保证措施。但实际上代码片段在内存中会分成更细的几个部分;

例如a++这个操作机器指令就至少有三条,CPU不保证三条操作中不会插入其他的操作,所以,即使是你写的代码是单进程的,因为CPU有N多代码片段要执行,CPU不能保证每一步都能使原子操作;

JVM就当成一个逻辑上的PC,类似的CPU模型,也会导致同样的问题。

一个java程序中可能会有多个代码片段需要getInstance,如果进程A和进程B同时getInstance,就会有概率出现getInstance时候验空会两个进程都得到个空,然后同时new一个新的对象导致实例过程不正确。

物理机上的X86 CPU有CAS模块硬件实现原子性操作,而java在早期是通过锁来实现的。用锁来保证一段时间内只有一个进程能访问到getInstance代码片段,从而防止出现A,B都getInstance的时候都会new操作。

而volatile的做法是,同时也是volatile的含义是:

每当局部变量需要读取volatile修饰的字段时候,JVM总能保证是从不会将读取的指令插入到上一条将本地内存往主存写的过程之间。