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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 张先庆 中级黑马   /  2013-7-23 21:23  /  6943 人查看  /  9 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 杨兴庭 于 2013-7-23 23:23 编辑

class Single
{
private Single(){}
private static Single s = null;
public static Single getInstance(){
   //判断一下,如果s依然是null,建立一个对象
   if(s == null)
  s = new Single();
   return s;
}
}

评分

参与人数 1技术分 +1 收起 理由
杨兴庭 + 1

查看全部评分

9 个回复

倒序浏览
本帖最后由 xscn 于 2013-7-23 21:38 编辑

从线程安全性上讲,不加同步的懒汉式是线程不安全的。
比如,有两个线程,一个是线程A,一个是线程B,它们判断条件满足都进来了,它们同时调用getInstance方法,那就可能导致并发问题。
当A、B线程并发的情况下,会创建出两个实例来,这样单例的控制在并发情况下就失效了。


懒汉式一般要用双重检查加锁判断的,视频里有讲
  1. class Single
  2. {
  3.         private static Single s = null;
  4.         private Single(){}
  5.         public static Single getInstance()
  6.         {
  7.                 if(s==null)//检查实例是否存在,如果不存在进入下面的synchronized代码块
  8.                 {
  9.                         synchronized(Single.class)
  10.                         {                               
  11.                                 if(s==null)//拿到锁后再次判断实例是否存在,如果不存在才创建实例
  12.                                         s = new Single();
  13.                         }
  14.                 }
  15.                 return s;
  16.         }
  17. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
杨兴庭 + 1

查看全部评分

回复 使用道具 举报
在多线程即楼上所说同步状态下会不安全,你先放下这个问题,看到多线程就明白了
回复 使用道具 举报
这个跟cpu的切换有关系,不加同步的懒汉式不安全,加了同步的懒汉式效率不高!楼上正解
回复 使用道具 举报
if(s == null)
  s = new Single();
如果多个线程在判断完 (s == null)为true都在s = new Single();之前给sleep()了,那么醒来后会直接创建对象,而不是重新判断.
导致了创建不止一个的对象.这就是懒汉式的不安全.

评分

参与人数 1技术分 +1 收起 理由
杨兴庭 + 1

查看全部评分

回复 使用道具 举报
1,懒汉式:
       public class Singleton{
            private static Singleton singleton = null;
            public static synchronized synchronized getInstance(){
                 if(singleton==null){                         1
                     singleton = new Singleton();       2
                 }
                return singleton;
            }
       } 2,     毕老师的原话:多个线程都获取cpu的执行权。cpu执行到谁,谁就运行。明确一点,在某一个时刻,只能有一个程序在运行。(多核除外)
        cpu在做着快速的切换,以达到看上去是同时运行的效果。我们可以形象把多线程的运行行为在互相抢夺cpu的执行权。这就是多线程的一
       个特性:随机性。谁抢到谁执行,至于执行多长,cpu说的算。
3,假设一个线程运行到 “1“那行代码它的执行权没了,这是又进来另一个线程,执行到”2“行代码处,此时它也没有执行权了,注意此时已经new
      了一个实例,那么该第一个线程运行了,它接着运行”2“行代码,此时就有了两个实例,它就不能保证是单例了。

评分

参与人数 1技术分 +1 收起 理由
杨兴庭 + 1

查看全部评分

回复 使用道具 举报
王瀛 高级黑马 2013-7-23 22:01:30
7#
懒汉式原型是使用同步方法,但是这样会降低效率,于是使用双重if语句+synchronized代码块改进。

因为单if判断有可能会在内存中产生多于一个的对象,这样就与使用单例模式的初衷不符了。

另外,可以使用枚举的方式实现单例(但是不推荐,开发中常用的还是饿汉式),代码比较简单
  1. enum Single{
  2. INSTANCE;
  3. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
杨兴庭 + 1

查看全部评分

回复 使用道具 举报
因为当一个线程运行到s为空的时候,他的执行权被抢走了,另外一个线程也运行到s为空这一步,这样的话两个线程都能获取实例。就会导致异常发生
回复 使用道具 举报
因为s是共享数据,当多个线程并发访问getInstance()方法时,就会有多条线程同时在操作共享数据s,这种情况是有可能发生的。比如:现在有两个线程A,B。线程A调用getInstace()方法,这时线程A已经进入getInstace()方法内,读 if(s == null)语句,突然之间就挂起了(这时有可能的哦)。然后线程B获得了执行权,调用getInstace()方法,这时线程B也进入getInstace()方法内,读 if(s == null)语句,执行s = new Single();于是就在堆内存中创建了对象S。当线程A醒来后,也执行s = new Single();于是就又创建了一个S!!!以此类推,当很多个线程同时操作s时,有可能会new出很多个对象,这就是懒汉式的不安全性。
修改后的代码:
class Single
{
private static Single s = null;
private Single(){}
public static Single getInstance(){
   if(s == null)
   {Synchronized(Single.class)
    { if(s == null)
       s = new Single();
     }
    }
   return s;
}
}

评分

参与人数 1技术分 +1 收起 理由
杨兴庭 + 1

查看全部评分

回复 使用道具 举报
这个牵涉到cpu的问题,仔细看看毕老师的视频教程,讲的很清楚
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马