黑马程序员技术交流社区
标题:
关于单例设计模式中懒汉式被多线程访问的问题。
[打印本页]
作者:
╰青青子佩ˊゝ
时间:
2014-4-1 18:24
标题:
关于单例设计模式中懒汉式被多线程访问的问题。
//单例设计模式中懒汉式在被多线程访问时,同步代码块中为什么要双重if语句判断?总想不清楚,求大神提点!
class Single
{
private static Single s = null;
private Single(){}
public static synchronized Single getInstance()
{
//老想不明白这里为什么要双重否定??
if(s == null)
{
synchronized(Single.class)
{
if(s == null)
s = new Single();
}
}
return s;
}
}
复制代码
作者:
清风有意
时间:
2014-4-1 18:41
楼主的代码貌似写错了吧?方法上应该没有synchronized这个关键字,因为里面有了。现在分析假如没有第一个if(n=null),那么就和在方法上加synchronized没有区别。在多线程进入的时候,考虑最坏的打算。两个线程都进入,而只有一个线程可以进入synchronized(Single.class),当这个线程出来时,另一个线程进入,但是synchronized里面还有一个判断if(n==null),此时n已经new出对象了。所以直接return n;所以不加第一个if(n==null)是可以的。
但是为什么要加上呢?因为每一个线程进来的时候都需要判断synchronized(Single.class)这个锁。很消耗时间。所以为了优化,而在synchronized(Single.class)前面加上判断if(n==null),此时如果单例设计已经完成,那么别的线程执行这个的话就会直接 return n; 而不用再进行判断synchronized(Single.class).
不知楼主明白了吗?
作者:
杨殿生
时间:
2014-4-1 19:07
外面if是判断s是否为空的,它的作用是减少了判断锁的次数,里面的if是当s为空时建立对象用的
作者:
刘一博
时间:
2014-4-1 20:47
本帖最后由 刘一博 于 2014-4-1 20:49 编辑
首先说里面的if()条件必须要有,判断是否已经初始化对象了
之所以外面加完了,里面还要加判断是为了防止,线程高并发都通过了外层的if条件判断
加synchronized是为了让多线程抢占锁,线程安全
在外层加if可以省去,但是多线程抢占锁会耗费资源,加上优化了代码,防止不必要的资源损失
作者:
闲人
时间:
2014-4-1 20:51
本帖最后由 闲人 于 2014-4-1 20:55 编辑
假如没有外面的if,那么程序运行时,
判定是否有锁
|--有锁,则暂停
|--没锁,判断是否为空
|---当空时,开始运行
|---当不空时,暂停
假如外面有if
程序会直接判定是否为空
|--当空时,运行以上内容
|--当不空时,暂停
双层if的好处是,可以节省判断锁的次数,降低内存的运行,让程序更快
作者:
╰青青子佩ˊゝ
时间:
2014-4-1 21:22
清风有意 发表于 2014-4-1 18:41
楼主的代码貌似写错了吧?方法上应该没有synchronized这个关键字,因为里面有了。现在分析假如没有第一个if ...
是多了个synchronized。 多谢,思路更清晰了。
作者:
帅哥哥
时间:
2014-4-1 21:41
楼主可以网上查查懒汉式双重判断的原因,有详细解答的。
http://plplum.blog.163.com/blog/static/31032400201241534840891/
简单的说,第一个if目的是提高效率的,第二个if的目的是出于安全考虑,确保只创建一个实例
1.第一个if的作用
假如有两个线程A,B同时进入函数(第6行),A的时间片到了,A在时间片内执行完了函数,那堆中已经有了一个实例,这时B的时间片到了,B判断第一个if,(s!=null),所以不用进锁,直接返回s,提高了效率,如果没有第一个if,那么B也会进锁,降低效率
2.第二个if的作用
假如有两个线程C,D同时进入第一个if(第9行),C的时间片到了,进锁(D不能进了,要等待),创建了一个实例,C创建完实例释放锁,D能进锁,这时,(s!=null),于是返回s,确保堆中只有一个实例
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2