双重检查锁定(Double check locked)模式经常会出现在一些框架源码中,目的是为了延迟初始化变量。这个模式还可以用来创建单例。下面来看一个 Spring 中双重检查锁定的例子。
这个例子中需要将配置文件加载到 handlerMappings
中,由于读取资源比较耗时,所以将动作放到真正需要 handlerMappings
的时候。我们可以看到 handlerMappings
前面使用了volatile
。有没有想过为什么一定需要 volatile
?虽然之前了解了双重检查锁定模式的原理,但是却忽略变量使用了 volatile
。
下面我们就来看下这背后的原因。
错误的延迟初始化例子
想到延迟初始化一个变量,最简单的例子就是取出变量进行判断。
这个例子在单线程环境交易正常运行,但是在多线程环境就有可能会抛出空指针异常。为了防止这种情况,我们需要使用 synchronized
。这样该方法在多线程环境就是安全的,但是这么做就会导致每次调用该方法获取与释放锁,开销很大。
深