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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 杨博 中级黑马   /  2013-3-19 18:59  /  1654 人查看  /  5 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 杨博 于 2013-3-19 19:40 编辑
  1. class Singleton
  2. {
  3. private static Singleton sngleton;

  4. private Singleton(){
  5. }

  6. public static Singleton getSingleton(){
  7. if(singleton==null)                            //判断对象是否为空
  8. synchronized (Singleton.class){
  9. if(singleton==null)                            //为什么还要判断
  10. singleton=new Singleton();
  11. }
  12. return singleton;
  13. }
  14. }
复制代码
问题如代码中,既然已经判断了,为什么还要再次判断,不太理解,求指导

评分

参与人数 1技术分 +1 收起 理由
贾文泽 + 1

查看全部评分

5 个回复

倒序浏览
如果是俩个线程同时调用get函数,第一次执行执行的时候,如果俩个线程同时进行判断,都判断为空,会做出两个对象,所以就会不再是单例模式,所以要进行第二次判断。
回复 使用道具 举报
考虑多线程的情况.
例如:1线程执行到第一个if 进行第一次判断,对象为null,于是进入同步代码块.
这时2线程进入第一个if,1线程还没有执行创建对象,于是对象依然为null.所以2线程在等待进入同步代码块.
1线程执行完创建对象,退出代码块,2线程进入,如果没有第二个if判断,2线程会认为对象依然为null,而继续创建.
这就不能保证单例了

评分

参与人数 1技术分 +1 收起 理由
贾文泽 + 1

查看全部评分

回复 使用道具 举报
单例模式的目的:建立唯一对象。它是利用synchronized 方法控制对类成员变量的访问,每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执行。
同步代码块的格式:

synchronized(同步对象)
{
    需要同步的代码;
}

AB两个并发线程访问同一个对象的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。synchronized关键字,代表这个方法加锁,相当于不管哪一个线程(例如线程A),运行到这个方法时,都要检查有没有其它线程B运行完这个方法后再运行此线程A。

回复 使用道具 举报
张东贤 来自手机 中级黑马 2013-3-19 20:27:01
报纸
很简单啊,电脑只能在某一时刻运行一个线程,所以,当运行第一个同步线程判断完后,电脑运行第二个线程,回来在运行时,条件变了,但是已经不会再次判断了,就会出错啊,明白?手机回帖的都伤不起啊,我痛苦啊来自: Android客户端
回复 使用道具 举报
先在代码里逐条解释
  1. class Singleton
  2. {
  3. private static Singleton sngleton;

  4. private Singleton(){
  5. }

  6. public static Singleton getSingleton(){
  7. //此时为非同步状态,占用资源较少,若有对象存在,即判定为false,则直接return已有对象
  8. if(singleton==null)                           
  9. synchronized (Singleton.class){
  10. //虽然这里和上面那句同为是否有对象存在判断,但意义不同,这里的判断是针对多线程共行时的同步状态进行的,[color=Red]上面判断的目的是为了增加效率,这句判断的目的是为了安全性[/color]
  11. if(singleton==null)                           
  12. singleton=new Singleton();
  13. }
  14. return singleton;
  15. }
  16. }
复制代码
这里的单例模式的优化较原版主要有两个改动,分别是增加了一个是否存在对象的判断以及一条同步代码块。
增加同步主要是为了应对多线程的情况,我们知道同步的目的主要是为了应对多个线程操作同一个资源的问题,显然在这里共同操作的资源就是我们定义的private static Singleton sngleton,而操作的具体动作是若无对象,则new一个对象,但是这里有个问题,同步是很占资源的,如果本来就有对象存在,自然不需再new一个,也自然不用再出现多线程操作同一个资源的问题,换言之,此时是不需要同步的,于是在同步代码面前,再加一个if(singleton==null) 的判断,这样的话,若已有对象存在,就不必进行同步,自然节省了资源,增强了代码的效率。
总结一下,额外增加了一个是否存在对象的判断是为了增强代码效率,增加同步是为了线程安全(同步代码中的判断自然也是如此)
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马