在本文中,我们将介绍在RxJava中创建Singleton对象的一些技术。 最重要的是,我们将学习Java中的双重检查锁定

Java中的Singleton模式是一种创新模式。 随着时间的流逝,人们开始关注Singleton模式的使用和实现。 这是由于单例的实现和使用方式存在一些非常根本的问题所致。

Java中的单例模式具有多种功能,例如:

  1. 确保只有一个类实例存在于JVM中。
  2. 提供对类实例的全局访问。
  3. 防止直接创建类实例的私有构造函数。
  4. 最适合用于日志记录,线程池,缓存等…

使用Java创建Singleton模式的三种基本方法。 我将列出所有这些内容,并告诉您单例模式是如何随着时间演变的,以及为什么双重检查锁定是当前最好的方法。

这是Java中Singleton模式的基本实现。

 class Example{     private Example mExample = null ;   public Example getInstance (){ if (mExample == null ) mExample = new Example (); return mExample; } // rest of the code...  } 

注意:构造函数在所有实现中都是私有的。

此代码将在多线程上下文中失败。 多个线程可以调用getInstance()方法并最终创建Singleton的多个实例。 这是不希望的行为。 Singleton的基本属性是,JVM中应该只有该类的单个实例。

优点:

  • 易于阅读。
  • 在单线程应用程序中可以正常工作。

缺点:

  • 在多线程上下文中将失败。
  • 多个线程可以创建此类的多个实例。
  • 将无法达到Singletons的目的。

一些聪明的人想到了创建单例的优雅解决方案。 我们使用synced关键字来防止线程同时访问getInstance()方法。

 class Example{     private Example mExample = null ;   public synchronized Example getInstance (){ if (mExample == null ) mExample = new Example (); return mExample; } // rest of the code...  } 

通过使用synced关键字,我们是JVM,一次只能让一个字段访问此方法。 这解决了多线程上下文的问题。

如果您看一下上面的代码,您会注意到我们已经使整个方法同步。 每个访问该方法的线程都将首先获取一个锁。

同步或获取锁是一种昂贵的方法。 确实会降低应用程序的性能。 如果您想进一步了解同步的性能开销,那么这个SO答案将是一个好的开始。

即使所有线程都获得了锁定,它也只是需要锁定的第一个线程。 初始化对象后,空检查足以在线程之间维护单个实例。

优点:

  • 确实很好地处理了多线程环境。
  • 容易明白。

缺点:

  • 每当线程尝试访问该方法时,获取不必要的锁定。
  • 锁定确实非常昂贵,并且许多线程都想获得一个锁定,这会导致严重的性能开销。

在先前的方法中,我们将整个方法同步为线程安全的。 但是同步不仅适用于方法。 我们也可以创建同步块。

在此方法中,我们将创建一个同步块而不是整个方法。

 class Example{     private Example mExample = null ;   public Example getInstance (){ if (mExample == null ){ synchronized (Example. class ){ if (mExample == null ) mExample = new Example (); } } return mExample; } // rest of the code...  } 

这是步骤顺序:

  • 第一个线程调用getInstance()方法。
  • 它检查实例是否为空(对于第一个线程,它为)。
  • 然后,它获取一个锁。
  • 检查该字段是否仍然为空?
  • 如果是,它将创建该类的新实例并初始化该字段。 最后,返回实例。
  • 其余线程不需要获取锁定,因为字段已经初始化,因此降低了同步命中率!

注意同步块之前和之后的多个空检查。 因此,名称为double check lock

优点:

  • 在多线程环境中工作。
  • 比同步方法具有更好的性能。
  • 只有第一个线程需要获取锁。
  • 以上方法中最好的。

缺点:

  • 一开始,双重null检查可能会造成混淆。
  • 不行!!

是的,上述方法存在一个细微问题。 它并不总是有效。

问题在于,编译器对程序的感觉与人眼的感觉截然不同。 根据我们的逻辑,首先,应创建Example类的实例,然后将其分配给mExample字段。

但是不能保证此操作顺序。 编译器可以自由地对语句进行重新排序,只要它不影响最终结果即可。

因此,例如,您可能最终会将部分初始化的对象分配给mExample字段。 然后其他线程将对象视为非空。 这导致线程使用部分初始化的对象,这可能导致崩溃

如今,编译器对您的代码进行了某些优化,使他们可以自由地对语句进行重新排序。 当编译器内联构造函数调用时,可能会发生重新排序。

Doug Lea写了一篇有关基于编译器的重新排序的详细文章。

Paul Jakubik发现了使用双重检查锁定无法正常工作的示例。

如果上述所有方法都容易失败,那么我们还剩下什么?

在J2SE 5.0中,Java的内存模型发生了很大变化。 volatile关键字现在可以解决上述问题。

Java平台不允许将易失字段的读取或写入与之前的任何读取或写入重新排序。

 class Example{     private volatile Example mExample = null ;   public Example getInstance (){ if (mExample == null ){ synchronized (Example. class ){ if (mExample == null ) mExample = new Example (); } } return mExample; } // rest of the code...  } 

当心:仅在JDK 5及更高版本中有效。 对于android开发人员,您最好选择使用Java 7及更高版本的Java。

希望您觉得本文有用。 如果您愿意,请在下面的评论部分中告诉我,我很乐意写更多这样的概念文章。

翻译自: https://www.javacodegeeks.com/2019/09/double-check-locking-java.html

Java中的双重检查锁定相关推荐

  1. Java盲点:双重检查锁定及单例模式

    时间:2009-08-11 19:20    来源:未知    作者:Peter Haggar 核心提示:Peter Haggar , 高级软件工程师, IBM 2004 年 5 月 01 日 所有的 ...

  2. Java 中的双重检查(Double-Check)

    转载自    Java 中的双重检查(Double-Check) 在 Effecitve Java 一书的第 48 条中提到了双重检查模式,并指出这种模式在 Java 中通常并不适用.该模式的结构如下 ...

  3. Java中的双重检查锁(double checked locking)

    起因 在实现单例模式时,如果未考虑多线程的情况,很容易写出下面的代码(也不能说是错误的): public class Singleton {private static Singleton uniqu ...

  4. java 双重检查锁_Java中可怕的双重检查锁定习惯用法

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

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

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

  6. java 双重检查锁 失效_关于多线程:为什么Java中双重检查锁定被打破?

    此问题与旧Java版本的行为以及双重检查锁定算法的旧实现有关 较新的实现使用volatile并依赖于稍微改变的volatile语义,因此它们没有损坏. 声明字段分配始终是原子的,除了long或doub ...

  7. singleton 类_在Java中对Singleton类进行双重检查锁定

    singleton 类 Singleton类在Java开发人员中非常常见,但是它给初级开发人员带来了许多挑战. 他们面临的主要挑战之一是如何使Singleton保持为Singleton? 也就是说,无 ...

  8. 在Java中对Singleton类进行双重检查锁定

    Singleton类在Java开发人员中非常常见,但是它给初级开发人员带来了许多挑战. 他们面临的主要挑战之一是如何使Singleton保持为Singleton? 也就是说,无论出于何种原因,如何防止 ...

  9. java 双重检查锁定及单例模式

    双重检查锁定及单例模式 全面理解这一失效的编程习语 Peter Haggar , 高级软件工程师, IBM Peter Haggar 是 IBM 在北卡罗来纳州的 Research Triangle ...

最新文章

  1. tensorflow错误:Shape (10, ?) must have rank at least 3
  2. 笔试算法题及解答(Python)
  3. 美团点评:基于Druid的Kylin存储引擎实践
  4. 【吴恩达机器学习】学习笔记——2.1单变量线性回归算法
  5. java 集合框架快速预览
  6. docker显示镜像的摘要信息
  7. iPhone是否越狱的检测方法
  8. t检验的p值对照表_统计学|各类统计检验方法大汇总
  9. 使用OpenResty搭建高性能服务端
  10. 计算机汉字录入技能怎么上,用手动录入怎么样把文件录入电脑?快速录入文字...
  11. webmax的剪切面和正对相机设置 图例
  12. iOS App Extensions之Share Extension
  13. CVPR2021:单目标跟踪
  14. 关于临时HY学长被安排拉二分题不想翻译找到DYM学长这件事
  15. python炫酷动画源代码_Python tkinter实现的图片移动碰撞动画效果【附源码下载】...
  16. 在线语音识别引擎及识别方法与流程
  17. Redis如何实现多可用区?
  18. 疯狂的 ICO 终于被全面叫停;9 月全球数据库排名,Oracle 跌势明显
  19. 全等三角形的判定方法
  20. 举个栗子!Tableau 技巧(113):在工作表中嵌入可切换网页

热门文章

  1. ssl2345-繁忙的都市
  2. 【数论】能量采集(P1447)
  3. 【树链剖分】【线段树】树的统计(金牌导航 树链剖分-1)
  4. 【暴力】I Liked Matrix!
  5. 可能是最全面的 Java G1学习笔记
  6. Spring MVC工作原理
  7. 架构师之路:从码农到架构师你差了哪些
  8. Java 集合系列04之 fail-fast总结
  9. java爬虫之基于httpclient的简单Demo(二)
  10. 漫画:什么是人工智能