黑马程序员技术交流社区
标题:
单例模式 懒汉式为什么不安全?
[打印本页]
作者:
张先庆
时间:
2013-7-23 21:23
标题:
单例模式 懒汉式为什么不安全?
本帖最后由 杨兴庭 于 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;
}
}
作者:
xscn
时间:
2013-7-23 21:32
本帖最后由 xscn 于 2013-7-23 21:38 编辑
从线程安全性上讲,不加同步的懒汉式是线程不安全的。
比如,有两个线程,一个是线程A,一个是线程B,它们判断条件满足都进来了,它们同时调用getInstance方法,那就可能导致并发问题。
当A、B线程并发的情况下,会创建出两个实例来,这样单例的控制在并发情况下就失效了。
懒汉式一般要用双重检查加锁判断的,视频里有讲
class Single
{
private static Single s = null;
private Single(){}
public static Single getInstance()
{
if(s==null)//检查实例是否存在,如果不存在进入下面的synchronized代码块
{
synchronized(Single.class)
{
if(s==null)//拿到锁后再次判断实例是否存在,如果不存在才创建实例
s = new Single();
}
}
return s;
}
}
复制代码
作者:
hx32
时间:
2013-7-23 21:34
在多线程即楼上所说同步状态下会不安全,你先放下这个问题,看到多线程就明白了
作者:
曹奎
时间:
2013-7-23 21:37
这个跟cpu的切换有关系,不加同步的懒汉式不安全,加了同步的懒汉式效率不高!楼上正解
作者:
☆今☆
时间:
2013-7-23 21:37
if(s == null)
s = new Single();
如果多个线程在判断完 (s == null)为true都在s = new Single();之前给sleep()了,那么醒来后会直接创建对象,而不是重新判断.
导致了创建不止一个的对象.这就是懒汉式的不安全.
作者:
康大玮
时间:
2013-7-23 21:47
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“行代码,此时就有了两个实例,它就不能保证是单例了。
作者:
王瀛
时间:
2013-7-23 22:01
懒汉式原型是使用同步方法,但是这样会降低效率,于是使用双重if语句+synchronized代码块改进。
因为单if判断有可能会在内存中产生多于一个的对象,这样就与使用单例模式的初衷不符了。
另外,可以使用枚举的方式实现单例(但是不推荐,开发中常用的还是饿汉式),代码比较简单
enum Single{
INSTANCE;
}
复制代码
作者:
周骑骏
时间:
2013-7-23 22:03
因为当一个线程运行到s为空的时候,他的执行权被抢走了,另外一个线程也运行到s为空这一步,这样的话两个线程都能获取实例。就会导致异常发生
作者:
の放下执著
时间:
2013-7-23 22:17
因为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;
}
}
作者:
王广亚
时间:
2013-7-23 23:18
这个牵涉到cpu的问题,仔细看看毕老师的视频教程,讲的很清楚
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2