双重检查锁定 问题

yzeaho 2014-07-30 11:39:46
http://blog.csdn.net/kufeiyun/article/details/6166673
看了上面这篇博文之后,还是没有明白 双重检查锁定的问题。
最纠结的问题是清单4 中的代码 //3 行没有运行完会释放锁?
感觉就是它释放锁了,才导致问题出现的,但是运行完了就有对象的引用了,没运行完它会释放锁?
如果运行完了还是没有对象引用的话,我们接着使用这个对象就会报空指针异常,就颠覆了我们之前写的代码了,
刚new出来的对象整可能为空?
忘大侠指导,我一直怀疑国内翻译的书,是不是翻译错了术语~~
...全文
577 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
yzeaho 2014-09-28
  • 打赏
  • 举报
回复
罢了,结贴~
humanity 2014-09-19
  • 打赏
  • 举报
回复
双重检查锁定只适合 那个变量从 null 变成 not null 的情况(也就是单例)。其它情况下没有什么实际意义。 第一次检查没有锁定的成本。如果它频繁地在 null 和 not null 之间切换的话,这第一个检查还不如直接省掉算了。
yzeaho 2014-09-16
  • 打赏
  • 举报
回复
还有人知道么
lliiqiang 2014-09-16
  • 打赏
  • 举报
回复
我觉得双重锁定检查没有问题。否则不使用双重锁定检查,仍然会出现内存模型错误.
as1dasd11 2014-09-16
  • 打赏
  • 举报
回复
我发现我打字太快 错别字很多,讲究吧。看懂你就明白了。 1买了房子 2装修房子 3 房子到你名下。
as1dasd11 2014-09-16
  • 打赏
  • 举报
回复
不用双重检查锁的单例没有线程安全问题 却有效率问题。 效率在于每次来的都要得到锁。 用双重检查锁的单例有线程安全问题 效率好一些。 线程安全问题在于 讲一个没有完全实例化的对象释放出去。
public static Singleton getInstance()
{
 
 if (instance == null)//4
  {
 
      synchronized(Singleton.class) {  //1
      if (instance == null)          //2
        instance = new Singleton();  //3
    }
  }
  return instance;
这段代码 中,一个线程看到第四步 发现 不为null,拿去使用了。但是实际是这个不为null的对象,并没有完全实例化。 原因在于: 3处 这个地方代码只有一行,真正意义上完成一个对象需要三步。 1,分配对象的内存空间 1买了房子 2,为该对象的属性赋值 2给房子装修 3,初始化该对象。 3 把名字给你。 这个顺序不一定,加入说 3 执行了 再执行2 就出问题了. 解决办法是 给instance的修饰加上volatile 。这上这个字后 保证不会重排序。。。。这样得到的就是正确的对象。 回答完毕。
HinanaiTenshi 2014-09-16
  • 打赏
  • 举报
回复
双检锁的问题在于对象创建中的进程抢占,不是任何场景都需要双检锁+volatile的。 而且java在1.2之后就已经有了更好的饿单例实现:利用内部类创建实例,简单高效,没有任何线程问题。
yzeaho 2014-08-05
  • 打赏
  • 举报
回复
用了双重锁定出问题,不用呢,如下代码,不是更加会出问题么

public static Singleton getInstance()
{
      synchronized(Singleton.class) {  //1
      if (instance == null)          //2
        instance = new Singleton();  //3
  }
  return instance;
csdn_java_coder 2014-08-04
  • 打赏
  • 举报
回复
引用 9 楼 u012724379 的回复:
volatile出现后,基本就不用考虑双重锁定的问题了; 如同单例模式中的一样;
不是吧,volatile不是会大大影响性能的吗? 双重锁定,最起码是使用的改变量的时候才锁啊,volatile是只要有变化,各线程全部更新一次。
-江沐风- 2014-08-03
  • 打赏
  • 举报
回复
volatile出现后,基本就不用考虑双重锁定的问题了; 如同单例模式中的一样;
  • 打赏
  • 举报
回复
JMM 的问题,在 JDK 1.5 以及后使用 volatile 关键字的话就不存在这个问题了。 至于 JDK 1.5 前 DCL 为什么会有问题,详细的还是需要看看专家们是怎么说的,参考以下文章: The "Double-Checked Locking is Broken" Declaration http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
grapepaul 2014-08-01
  • 打赏
  • 举报
回复
java的内存模型中,构造函数的执行和instance的内存分配是无顺序的,不是说一定在构造函数执行完,instance才不等于null。 所以存在一种情况,构造函数执行过程中,instance已经不为null,而刚好此时另一个getInstance()调用发生,直接返回了一个初始化不完整的instance
二萌无双 2014-08-01
  • 打赏
  • 举报
回复
public static Singleton getInstance()
{

 if (instance == null)
  {

      synchronized(Singleton.class) {  //1
      if (instance == null)          //2
        instance = new Singleton();  //3
    }
  }
  return instance;
个人认为问题不是出现在释放锁 而是博主说的代码优化 就是在创建对象的时候可能会存在1分配内存2创建引用关系3初始化对象 这样的优化创建方式 这样在//3处可能尚未完全创建对象时即2创建引用关系时由于CPU调度当前线程失去CPU 这时在最外层的 if (instance == null)处(非//2处)条件判断失败其他线程会直接返回instance 而此时线程1并未失去锁 另外,据说jdk1.5以后此问题已经被优化了。。。但是。。不太肯定。。。
yzeaho 2014-08-01
  • 打赏
  • 举报
回复
第七,十四行是哪行代码
yzeaho 2014-08-01
  • 打赏
  • 举报
回复
双重检查结论是错误的用法,但我怎么看都觉的不会有问题
gqqnb 2014-08-01
  • 打赏
  • 举报
回复
或者这么说,设有两个线程A、B。 线程A将要运行第7行,由于CPU调度原因被阻塞。线程B现在从第1行开始运行,一直运行到第14行,instance被创建。 然后线程A继续,运行第7行,成功获得锁。请问它此时要不要创建instance的实例?
gqqnb 2014-08-01
  • 打赏
  • 举报
回复
我没有读完全文,也不知道你为什么说“没有运行完会释放锁”,
public static Singleton getInstance()
{

 if (instance == null)
  {

      synchronized(Singleton.class) {  //1
      if (instance == null)          //2
        instance = new Singleton();  //3
    }
  }
  return instance;

}
先检查instance是否为null,如果为null则创建新实例。这时锁定Singleton.class。锁定进去了之后,再检查一下instance是否为null,就怕刚才有人已经把instance创建好了。 锁定前后各检查一次,就叫双重检查。
whos2002110 2014-07-31
  • 打赏
  • 举报
回复
其实不用太纠结什么“对象分配了引用,但还没创建完毕,另外一个线程发现引用不为null,使用报错“。 就按代码逻辑去理解, DCL配合volatile是完全正确的单例模式!

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧