gpt4 book ai didi

双重检查锁定模式Java中的陷阱案例

转载 作者:qq735679552 更新时间:2022-09-28 22:32:09 32 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章双重检查锁定模式Java中的陷阱案例由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

1、简介

双重检查锁定(也叫做双重检查锁定优化)是一种软件设计模式.

它的作用是减少延迟初始化在多线程环境下获取锁的次数,尤其是单例模式下比较突出.

  • 软件设计模式:解决常用问题的通用解决方案。编程中针对一些常见业务固有的模版。
  • 延迟初始化:在编程中,将对象的创建,值计算或其他昂贵过程延迟到第一次使用时进行。
  • 单例模式:在一定范围内,只生成一个实例对象。

  。

2、Java中的双重检查锁定

单例模式我们需保证实例只初始化一次.

下面例子在单线程环境奏效,多线程环境下会有线程安全问题(instance被初始化多次).

private static Singleton instance;public static Singleton getInstance() {  if (null == instance) {      instance = new Singleton();  }  return instance;}

下面例子主要是性能问题。首先加锁操作开销很大,因为线程安全发生在对象初始化,而这里做了做了全局控制,造成浪费.

public synchronized static Singleton getInstance() {  if (null == instance) {      instance = new Singleton();  }  return instance;}

为了控制线程安全又能保证性能,双重检查锁定模式出现.

public static Singleton getInstance() {  if (null == instance) {      synchronized (Singleton.class) {          if (null == instance) {              instance = new Singleton();          }      }  }  return instance;}

逻辑如下:

双重检查锁定模式Java中的陷阱案例

我们分析一下执行逻辑:

假设有三个线程 T1 T2 T3 ,依次访问 getInstance 方法.

  • T1 第一次检查为Null 进入同步块,T1持有锁,第二次检查为Null 执行对象创建。
  • T2 第一次检查为Null 进入同步块,T2等待T1释放锁,锁释放后,T2进入执行第二次检查不为Null,返回实例对象。
  • T3 第一次检查不为Null,直接返回对象。

双重检查锁定模式Java中的陷阱案例

上面一切似乎很完美,但是这里面存在陷阱。根据Java内存模型我们知道,编译器优化处理会进行重排序.

instance = new Singleton() 大体分两个步骤; 。

  • 1 创建初始化对象;
  • 2 引用赋值。

而 1 2 步骤可能颠倒,会造成对象属性在初始化前调用的错误.

private static Singleton instance;...instance = new Singleton();...public class Singleton {  private int age;  public Singleton() {      this.age = 80;  }}

这种细微的错误不容易出现,但是它的确存在。大家可以参考下面这份报告,里面详细记录这个问题.

双重检查锁定模式Java中的陷阱案例

http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html 。

  。

3、列举方案

报告里面也列举了几种解决方案 。

3.1 利用 ThreadLocal

private static final ThreadLocal<Singleton> threadInstance = new ThreadLocal<>();public static Singleton getInstance() {  if (null == threadInstance.get()) {      createInstance();  }  return instance;}private static void createInstance() {  synchronized (Singleton.class) {      if (instance == null)          instance = new Singleton();  }  threadInstance.set(instance);}

3.2 利用volatile(解决重排序问题)

private volatile static Singleton instance;public static Singleton getInstance() {  if (null == instance) {      synchronized (Singleton.class) {          if (null == instance) {              instance = new Singleton();          }      }  }  return instance;}

下面是不同方案下的性能比较报告 。

http://www.cs.umd.edu/~pugh/java/memoryModel/DCL-performance.html 。

  。

4、总结

本章节主要记录了双重检查锁定模式使用中应该注意的细微事项.

请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。

原文链接:https://www.onlythinking.com/ 。

最后此篇关于双重检查锁定模式Java中的陷阱案例的文章就讲到这里了,如果你想了解更多关于双重检查锁定模式Java中的陷阱案例的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com