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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 潘星 中级黑马   /  2012-8-11 00:55  /  1766 人查看  /  3 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

class Single//饿汉式
{
        private Single(){}
        private static  Single s=new Single();
        public static Single getSingle()
        {
                return s;
        }
}
class Single//懒汉式
{
        private Single(){}
        private static  Single s=null;
        public static Single getSingle()
        {
                if(s==null)
                        A-->        懒汉式的这个地方为什么会出现安全隐患?
                        B-->        还有就是既然是为了得到一个对象,为什么要用
                                2个或多个线程来调用这个函数呢, 在什么情况下
                                    会有多个线程来同时调用这个函数?

                s=new Single();
                return s;
        }
}

评分

参与人数 1技术分 +1 收起 理由
张立江 + 1 赞一个!

查看全部评分

3 个回复

倒序浏览
s为共享数据,如果多个线程并发访问getSingle()的话,有可能A线程在判断s是否为空后sleep了,而B有线程这时来了,也判断完也sleep了,那么当A被唤醒的时候会给s赋值,而后面B醒了,这时它已经判断过为空了,但是实际上s已经不为空了,但是这时B还会给S赋值,那么就造成了类的不唯一性,这就是带来的安全隐患

评分

参与人数 1技术分 +1 收起 理由
张立江 + 1 回答的不错!

查看全部评分

回复 使用道具 举报
本帖最后由 杜佳瑞 于 2012-8-11 13:28 编辑

1,懒汉式的这个地方为什么会出现安全隐患?
因为在多个线程操作这个共享对象时,A线程先执行,判断完null后并没有创建对象,这时释放了系统资源;然后B线程开始执行,因为前面A并没有创建对象,对象s这时还是null,而B判断完了也释放资源,A拿到执行权后开始创建对象,之后B拿到执行权,也会创建一个对象,这样就不能保证对象的唯一性。
2,还有就是既然是为了得到一个对象,为什么要用2个或多个线程来调用这个函数呢, 在什么情况下会有多个线程来同时调用这个函数?
在现实生活中,多个线程同时操作一个对象的例子很多呀,比如视频中的买票例子,再比如系统的配置文件,不同的用户对系统操作后都会修改这个配置文件,所以不能每个用户来了之后都创建自己的配置文件吧,这就要求这个文件的唯一性,所以引出了单例设计模式。而懒汉式在单例设计模式中很常见。这种方法对象延迟加载,效率高,只有在使用的时候才实例化对象,但容易出现安全隐患,所以为了解决这个问题,引出了同步锁的概念。
class Single//懒汉式
{
        private Single(){}
        private static  Single s=null;
        public static Single getSingle()
        {
               if(s==null)//判断是否为空如果不为空直接return s,避免上锁,提高程序效率
               {
                     synchronized(Single.class)//线程到这里后先上锁,就是前面线程放弃了执行权,后面线程也进不去,解锁后下一个线程还要判断是否为空,这时s已不为空,所以不会再建新对象,继而保证了共享对象的唯一。
                     {
                            if(s==null)
                                  s=new Single();
                      }
               }
               return s;
        }
}
回复 使用道具 举报
首先懒汉式确实是存在安全隐患的。这总隐患主要在多线程并发的时候容易出现。比如一个售票系统。售票系统是能满足许多人同时买票这个功能的,若使用懒汉式的话,加入有甲乙丙三个人同时买票,这三个人恰巧都在Single还没创建对象时调用了getSinle()方法并对s进行了判断,此时s=null,三人都符合(s==null)这个条件,所以三人便会相继创建对象new Single();于是便返回了3个不同的Single对象。而饿汉式,当类加载的时候该静态变量 private static  Single s=new Single();就随之而存在了,最关键一点静态变量是被所有对象共享的只加载一次并且在饿汉式的get方法中没有对其做变化,所以以后所有返回的s均为同一个变量s。

一个对象在使用前就已经存在且静态修饰,在随后的方法中不对其做变动(如赋新值等)那么他就是唯一的不变得,如在以后发生了赋新值等操作就可能会在多线程操作时发生对象不唯一。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马