一个懒汉式单例缓存
1 public class Singleton { 2 private static volatile Singleton singleton = null; 3 4 private Singleton(){} 5 6 public static Singleton getSingleton(){ 7 if(singleton == null){ 8 synchronized (Singleton.class){ 9 if(singleton == null){ 10 singleton = new Singleton(); 11 } 12 } 13 } 14 return singleton; 15 } 16 }
这种编写方式被称为“双重检查锁”,主要在getSingleton()方法中,进行两次null检查。这样能够极大提高并发度,进而提高性能。毕竟在单例中new的状况很是少,绝大多数都是能够并行的读操做,所以在加锁前多进行一次null检查就能够减小绝大多数的加锁操做,也就提升了执行效率。可是必须注意的是volatile关键字,该关键字有两层语义。第一层语义是可见性,可见性是指在一个线程中对该变量的修改会立刻由工做内存(Work Memory)写回主内存(Main Memory),因此其它线程会立刻读取到已修改的值,关于工做内存和主内存可简单理解为高速缓存(直接与CPU打交道)和主存(平常所说的内存条),注意工做内存是线程独享的,主存是线程共享的。volatile的第二层语义是禁止指令重排序优化,咱们写的代码(特别是多线程代码),因为编译器优化,在实际执行的时候可能与咱们编写的顺序不一样。编译器只保证程序执行结果与源代码相同,却不保证明际指令的顺序与源代码相同,这在单线程并没什么问题,然而一旦引入多线程环境,这种乱序就可能致使严重问题。volatile关键字就能够从语义上解决这个问题,值得关注的是volatile的禁止指令重排序优化功能在Java 1.5后才得以实现,所以1.5前的版本仍然是不安全的,即便使用了volatile关键字。安全