首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

懂得静态变量惰性初始化的双检锁模式

2012-10-26 
理解静态变量惰性初始化的双检锁模式??对于双检锁,其实有多种不同的用法,有很多种用法是无论如何不会出现

理解静态变量惰性初始化的双检锁模式

?

?对于双检锁,其实有多种不同的用法,有很多种用法是无论如何不会出现问题的.我最初用双检锁来获取jndi对象时,立即有人告诉我双检锁是不安全的,我笑着告诉他:是否安全我比你更有把握.

?

    private static MyObect obj;    private Date d = new Data();    public Data getD(){return this.d;}    public static MyObect  getInstance(){        if(obj == null){            synchronized(MyObect .class){                if(obj == null)                    obj = new MyObject();//这里            }        }        return obj;    }}
?

?????? 一个线程A运行到"这里"时,对于A的工作区中,肯定已经产生一个MyObect对象,而且这时这个对象已经完成了Data d.现在线程A调用时间到,执行权被切换到另一个线程B来执行,会有什么问题呢?如果obj不为null,线程B获得了一个obj,但可能obj.getD()却还没有初始化.为什么?既然obj已经可见了(线程A还没有离开同步块),而d却不可见呢?如果d不可见,那么obj也应该为null啊?线程B应该等待A释放同步块啊?事实上,对于"这里"这条语句,线程A还没有离开同步块.因为没有"离开同步块"这个条件,线程a的工作区没有强制与主存储器同步,这时工作区中有两个字段obj,d 到底先把谁同步到主存储区,没有条件限制,虽然在线程A的工作区obj和d都是完整的,但有JSL没有强制不允许先把obj映射到主存储区,如果哪个jvm实现按它的优化方案先把工作存储器中的obj同步到主存储器了,这时正好线程B获取了,而d却没有同步过去,那么线程B就获取了obj的引用却找不能obj.getD();

?????? 我们发现,其实对于安全性问题都是基于即时构造对象这样的条件下的.如果你把DCL用来控制其它不重复操作,它就不会出现这样的问题,就象上面从JNDI中查找DataSource,因为查找本身是耗时的,所以我用DCL来控制"查找"这个行为而不是控制对象本身.其实还有很多可以正确应用DCL的地方.象JLive,OFBiz这些开源项目中都在大量应用DCL,当然我不是推荐大家都去用DCL,而是如果需要而且合适就去用.有些问题可以用其它方法来代替.只要你能真正明白它在什么时候是不安全的,你就可以安全地使用DCL.

?

热点排行