volatile跟双锁模式的代码分析
volatile和双锁模式的代码分析public class CachePool{private volatile static CachePool sharedPoolpri
volatile和双锁模式的代码分析
public class CachePool{ private volatile static CachePool sharedPool; private CachePool(){} public static CachePool getSharedPool(){ if(sharedPool==null) { synchronized(CachePool.class){ if(sharedPool==null){ sharedPool=new CachePool(); } } } return sharedPool; } //其他方法} 以上是存取CachePool对象的一段代码。
这里用到了volatile和两个if block来存取唯一化的CachePool的对象。
为什么既然这里用到了volatile,为什么要用到两个if block呢?
为什么不把synchronized来定义getSharedPool()方法呢?
假设我们synchronized整个getSharedPool(),那么我们每次用CachePool.getSharedPool()去取得sharedPool对象的时候,都要执行同步,这样会对性能造成影响。因此我们把syncronized抽开,放到第一个if block里面去执行,这样就保证了,当sharedPool对象取得之后,就不用再去执行这个同步化的if block。
我们假设两个线程t1和t2,分别开始在栈1和栈2执行getSharedPool()方法,t1判断到sharedPool是null, t2也判断是null, 因此t1, t2同时进入第一个if block, 假设t1比t2稍快执行同步部分,t1就率先实例化了CachePool这个类,把实例化的sharedPool返回,并把钥匙交给t2,t2要进入这个t2内存空间的cachePool还是null吗?如果sharedPool对象没有声明volatile,t2内存里读取的值就还是null,那么就还要new一次!不过这里sharedPool被volatile了,t2和t2对这个值是共享内存,因此t2读到的不再是null,因此,不再执行第二个if block,直接返回第一个new出来的对象的引用。
之后的线程调用getSharedPool(),第一个if block之后就直接return t1实例化出来的引用了,不再执行同步化的部分。
volatie和两个if block,加上一个syncronized,保证了sharedPool的对象唯一。