A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 朝花夕拾 中级黑马   /  2012-11-18 22:15  /  1703 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 张雄 于 2012-11-22 22:30 编辑

现在有如下代码:
If(instance == null) {
synchronized(Single.class) {
        if(instance == null) {
instance = new Single();
        }
}
}
return instance;
本人觉得在该代码中,执行一次后则该同步代码块结束,双重判断不存在效率问题,求高手解释!!!

评分

参与人数 1技术分 +1 收起 理由
奋斗的青春 + 1 很给力!

查看全部评分

4 个回复

倒序浏览
如果没有外层的判断,则每一次线程到这里之后都需要一个个的来等待锁,比较麻烦;
而加了外层判断后,就是刚开始的线程判断需要等待,在创建实例之后的线程再来访问的时候,直接就可以
跳过去了,而不需要锁了
回复 使用道具 举报
首先,如果把if(install==null) 这一句转换成汇编代码后只有一句 JZ XXX
sync代码块相比较if判断,汇编指令还会多些,
而电脑每秒执行的指令数几十上百万条
所以大家误认为的判断会造成效率问题是不对的,单纯的判断是不会造成效率问题的,
但是,不必要的操作是被认为是影响效率的,
比如LZ的代码,如果这段代码只被一处调用,这样写是完全没有必要的,而且是算效率问题的
只有在多个线程同时调用这段代码时,才可以这样写,
不过想new instance()这样的操作一般都是使用单例模式,而不是这样的sync块+多重判断

点评

呵呵 , 自娱自乐 。  发表于 2012-11-18 23:38
回复 使用道具 举报
我是这样理解的,首先我们先看一下懒汉式原有的代码
if(instance==null){
instance = new Single();
}
假如我们使用了多线程技术,线程A进来了判断instance等于null满足,执行权被切换走,等待
线程B进来了,判断instance等于null线程B也等待,假如A线程获得执行权创建了对象,C线程不在
判断标记直接又创建了对象,这样内存中就存在了两个对象。
如果我们在方法上加了同步函数,A线程进来创建了对象并返回,B线程进来也要判断锁,instance不为
null这样我们就解决了问题,但是其他线程进来都需要判断锁这样效率很低。
If(instance == null) {
synchronized(Single.class) {
        if(instance == null) {
instance = new Single();
        }
}
}
return instance;
我们就可以用同步代码块的
形式创建锁,但是这样和同步函数是一样的,所以在同步代码块上加了一层判断,A线程执行完毕,B线程在
第一层判断不为null就不在执行了,这样做提高了效率。

评分

参与人数 1技术分 +1 收起 理由
古银平 + 1 赞一个!

查看全部评分

回复 使用道具 举报
其实这个也不太好的。如:
class Single   
{   
    private static Single singleObj = null;     
    private Single(){ }     
    public static  Single getSingleInstance() {   
            if(singleObj==null){                                //AA
                    synchronized(Single.class){
                             if(singleObj==null )  //BB
                                    singleObj = new Single();
                    }
            }            
        return singleObj;                 //CC
    }   
}
可是实际上这个还是有问题的。
假设线程1执行到了AA那里,它判断对象为空,于是线程1执行到BB 去初始化这个对象,但初始化是需要耗费时间的,

但是这个对象的地址其实已经存在了。此时线程2也执行到了AA那里,它判断不为空,于是直接跳到CC得到了这个对象。

但是,这个对象还没有被完整的初始化!得到一个没有初始化完全的对象有什么用!!没有意义。

最好的单例设计就是内部类:

代码如下:

class Single {
        private Single(){}
        
        private static class SingleHolder{
                public static final Single instance=new Single();
        }
        
        public static Single getInstance(){
                return SingleHolder.instance;
        }
        
}
这种方式兼具饿汉式和懒汉式优点。而且,JLS(Java Language Sepcification)会保证这个类的线程安全。

具体请看我的帖子:  http://bbs.itheima.com/thread-30600-1-1.html
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马