java 双重检查锁

本文讨论的问题不是新问题,但即使是经验丰富的开发人员也仍然很棘手。 单例模式是常见的编程习惯用法。 但是,当与多个线程一起使用时,必须进行某种类型的同步,以免破坏代码。

在相关文章中,我们的JCG合作伙伴来自The Khangaonkar Report的 Manoj Khangaonkar 详细检查了双重检查的成语,以了解其崩溃之处,并提出了所有可能的解决方案:

免得他说些什么:

Java中的双重检查锁定问题已得到充分证明。 但是,即使是经验丰富的程序员也可能会过分热衷于尝试优化代码同步,从而创建单例并成为陷阱。

考虑代码

public class Sample {private static Sample s = null ;public static Sample getSample() {if (s == null) {s = new Sample() ;}return s ;}
}
清单1

此代码不是线程安全的。 如果2个线程t1和t2同时进入getSample()方法,则它们很可能获得不同的样本实例。 通过将synced关键字添加到getSample()方法,可以轻松解决此问题。

public class Sample {private static Sample s = null ;public static synchronized Sample getSample() {if (s == null) {s = new Sample() ;}return s ;}
}
清单2

现在,getSample方法可以正常工作。 在进入getSample方法之前,线程t1获得一个锁。 需要进入该方法的任何其他线程t2将阻塞,直到t1退出该方法并释放锁为止。 代码有效。 生活很好。 这是精明的程序员在不注意的情况下可以超越自己的地方。 他将注意到,实际上,仅对创建实例的getSample的第一次调用需要进行同步,而仅返回s的后续调用将付出不必要的代价。 他决定优化代码以

public class Sample {private static Sample s = null ;public static Sample getSample() {if (s == null) {synchronized(Sample.class) {s = new Sample() ;}}return s ;}
}
清单3

我们的Java专家很快意识到该代码与清单1所存在的问题相同。 因此,他进一步对其进行了微调。

public class Sample {private static Sample s = null ;public static Sample getSample() {if (s == null) {synchronized(Sample.class) {if (s == null) {s = new Sample() ;}}}return s ;}
}
清单4

通过在同步块中添加额外的检查,他确保了只有一个线程将创建该示例的实例。 这是双重检查模式。 我们的专家的朋友,一位Java专家,好友检查了该代码。 代码已签入,产品已发货。 生活好吗?

! 假设线程t1进入getSample。 s为空。 它锁了。 在同步块内,它检查s是否仍然为null,然后执行Sample的构造函数。 在构造函数执行完成之前,将t1换出,并且t2得到控制。 由于构造函数未完成,因此s被部分初始化。 它不为null,但具有一些损坏或不完整的值。 当t2进入getSample时,它将看到s不为null并返回一个损坏的值。

总之,仔细检查模式不起作用。 选项是在清单2所示的方法级别进行同步,或者放弃同步并使用一个静态字段,如下所示。

public class Sample {private static Sample INSTANCE = new Sample();public static Sample getSample()  {return INSTANCE ;}
}
清单5

好是好人的敌人!

拜伦

相关文章:

  • Java最佳实践系列
  • 正确记录应用程序的10个技巧
  • 每个程序员都应该知道的事情
  • 生存在荒野西部开发过程中的9条提示
  • 软件设计法则
  • JDK中的设计模式

翻译自: https://www.javacodegeeks.com/2011/03/dreaded-double-checked-locking-idiom-in.html

java 双重检查锁

java 双重检查锁_Java中可怕的双重检查锁定习惯用法相关推荐

  1. java未检查异常_Java中已检查和未检查的异常

    java未检查异常 Java有两种类型的异常-已检查和未检查. 简而言之,选中的是指开发人员可以从异常中合理恢复的情况,而未选中的异常是无法处理的编程错误. 本文介绍了何时使用哪种. 但这不是那么简单 ...

  2. java 共享锁 独占锁_java中的公平锁、非公平锁、可重入锁、递归锁、自旋锁、独占锁和共享锁...

    一.公平锁与非公平锁 1.1 概述 公平锁:是指多个线程按照申请锁的顺序来获取锁. 非公平锁:是指在多线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取到锁,在高并发的情 ...

  3. java 守护线程 作用_java中守护线程的一些概念和用法

    网上的资料中,守护线程的功能一般都是"只要当前JVM实例中尚存任何一个非守护线程没有结束,守护线程就全部工作:只有当最后一个非守护线程结束是,守护线程随着JVM一同结束工作,Daemon作用 ...

  4. Java中可怕的双重检查锁定成语

    本文讨论的问题不是新问题,但即使是经验丰富的开发人员也仍然很棘手. 单例模式是常见的编程习惯. 但是,当与多个线程一起使用时,必须进行某种类型的同步,以免破坏代码. Khangaonkar报告中的 J ...

  5. java中乐观锁_Java中乐观锁与悲观锁的实现

    锁(locking) 业务逻辑的实现过程中,往往需要保证数据访问的排他性.如在金融系统的日终结算 处理中,我们希望针对某个cut-off时间点的数据进行处理,而不希望在结算进行过程中 (可能是几秒种, ...

  6. java多线程 线程安全_Java中的线程安全

    java多线程 线程安全 Thread Safety in Java is a very important topic. Java provides multi-threaded environme ...

  7. java 共享锁 独占锁_Java并发编程锁之独占公平锁与非公平锁比较

    Java并发编程锁之独占公平锁与非公平锁比较 公平锁和非公平锁理解: 在上一篇文章中,我们知道了非公平锁.其实Java中还存在着公平锁呢.公平二字怎么理解呢?和我们现实理解是一样的.大家取排队本着先来 ...

  8. java 验证码透明背景_Java中的证书透明度验证

    java 验证码透明背景 因此,我有一个幼稚的想法,即除了证书有效性检查(在Java中)之外,将证书透明性验证作为每个请求的一部分也很容易. 牺牲了整个周末的一半时间,我可以证明这并不是一件小事. 但 ...

  9. java构造器详解_Java中关于构造器的使用详解

    这篇文章主要介绍了Java构造器使用方法及注意事项的相关资料,这里举例说明如何使用构造器及需要注意的地方,需要的朋友可以参考下 Java构造器使用方法及注意事项 超类的构造器在子类的构造器运行之前运行 ...

最新文章

  1. 针对访问控制列表ACL 与 基于角色的访问控制RBAC进行简单介绍
  2. 在emu8086中学习几个汇编语言显示字符串的小例子
  3. 42、Power Query-Text.Remove函数应用
  4. 云炬Android开发笔记 5-3,4Restful请求的处理
  5. superset可视化-deck.gl 3D Hexagon与deck.gl Grid与deck.gl Screen Grid
  6. R语言观察日志(part1)--subset函数
  7. mybatis 二级缓存使用注意
  8. “滚蛋吧”扎克伯格!
  9. bad interpreter: No such file or directory解决
  10. OpenCV关于隐马尔科夫模型的结构和函数
  11. 【程序人生】从外包到大厂,你知道我这一个月是怎么过的吗?
  12. [转载]Delta Lake、Iceberg 和 Hudi 三大开源数据湖不知道如何选?那是因为你没看这篇文章
  13. Java实现简单日期计算功能
  14. 1259_STM32CubeProgrammer的简单使用
  15. Apache HBase
  16. 消息重试框架 Spring-Retry 和 Guava-Retry,这个框架有点意思
  17. 《BackTrack 5 Cookbook中文版——渗透测试实用技巧荟萃》目录—导读
  18. 计算机图形学(二):三维图形变换及应用(平移、旋转、缩放、仿射)
  19. 前端工作随笔日记 Day03
  20. 澳门惊现Google地图街景车

热门文章

  1. 循环输入某同学 S1 结业考试的 5 门课成绩,并计算平均分
  2. java中判断 101-200 之间有多少个素数,并输出所有的素数
  3. JS进行性能测试(计时)
  4. 在mysql中插入日期
  5. css 浏览器调试中不可见_前端入门必会的初级调试技巧
  6. XML——XML Schema
  7. 特权级概述(哥子就想知道CPU是如何验证特权级的)GATE+TSS
  8. 基于Apache POI 从xlsx读出数据
  9. 日发帖 发帖频率 发帖时段_先发帖
  10. java 多线程和并行编程_Java 8中的并行和异步编程