文章目录

    • 问题的根源:JDK 1.7 的设计缺陷
    • 为什么必须解决这个问题?
      • 1\. 故障等级完全不同 💣
      • 2\. JDK 1.8 的解决方案:一石二鸟 🦅
      • 3\. 为“不小心”的开发者提供一层保障 🛡️
    • 结论

这是一个非常好的问题,它直击了技术演进的核心: 即使不能解决所有问题,也要优先解决最致命的问题

简单来说,解决环形链表问题,并不是为了实现线程安全,而是为了消除一个在并发场景下会导致服务器CPU 100%直至宕机的“定时炸弹”

这是一个关于**故障严重性(Failure Severity)**的权衡问题。


问题的根源:JDK 1.7 的设计缺陷

在 JDK 1.7 中,HashMap 扩容(resize)时转移数据的 transfer 方法使用了头插法

  • 头插法:在将旧数组的元素转移到新数组时,新来的元素总被放在链表的头部。
  • 问题所在:在单线程下,头插法会使链表顺序反转,这没问题。但在多线程并发扩容时,两个线程可能同时操作同一个链表。一个线程执行一半被挂起,另一个线程完成了扩容导致链表反转。当第一个线程恢复执行时,它会基于一个已经改变的链表继续操作,这会导致链表节点的 next 指针互相指向,最终形成一个环形链表

这个环形链表一旦形成,后续对该位置的 get() 操作就会陷入无限循环,导致CPU占用率飙升到100%,整个应用或服务器都会被拖垮。


为什么必须解决这个问题?

现在回到你的核心问题:既然HashMap本来就不是线程安全的,并发使用时数据丢失、不一致等问题都可能发生,为什么还要专门修复环形链表这个bug?

1. 故障等级完全不同 💣

HashMap 在并发下可能遇到的问题可以分为两类:

  • 数据不一致 (Data Inconsistency): 比如两个线程同时 put,一个线程的数据覆盖了另一个,导致数据丢失。这属于数据问题,虽然也很糟糕,但通常不会让整个应用程序崩溃。
  • 致命的系统崩溃 (Fatal System Crash): 环形链表导致的无限循环,会耗尽CPU资源,引起拒绝服务(DoS)。这是一个系统级的灾难性故障。

打个比方:
数据不一致就像是两个售票员卖了同一张电影票,会导致顾客(数据)冲突,需要业务逻辑去处理。
而环形链表就像是售票系统的后台代码进入了死循环,整个售票系统都瘫痪了,谁也买不了票。

显然,消除一个能让服务器宕机的Bug,其优先级远高于处理一般的数据不一致问题

2. JDK 1.8 的解决方案:一石二鸟 🦅

JDK 1.8 对 HashMap 进行了重大重构,主要做了两件事,顺便解决了环形链表问题:

  • 引入红黑树 (Red-Black Tree): 这是1.8最大的性能优化。当链表长度超过一定阈值(默认为8)时,链表会转化为红黑树,将该位置的查找时间复杂度从 O(n) 优化到 O(log n)。这是重构的主要动机之一。

  • 修改扩容算法为“尾插法”: 在数据转移时,保持链表元素的原有顺序,将元素依次插入到新链表的尾部。因为顺序保持不变,就不会出现1.7中指针反转交错形成环路的情况。这个修改顺手就根除了环形链表这个“定时炸弹”

所以,JDK 团队在进行性能优化的同时,也修复了这个已知的、非常严重的设计缺陷。

3. 为“不小心”的开发者提供一层保障 🛡️

虽然官方文档明确指出 HashMap 非线程安全,但现实中总有开发者会误用或者在一些自认为安全的场景下不慎造成并发。

与其留着一个会导致服务器崩溃的“地雷”,不如让它在被误用时表现得“温和”一些。JDK 1.8 之后,即使你在并发场景下误用了 HashMap,最可能发生的是数据丢失,而不再是整个应用的崩溃。这是一种更“安全失败”(Fail-Safe)的设计哲学。


结论

总而言之,从1.7到1.8的演进,解决环形链表问题并非为了让 HashMap 变得线程安全,而是:

  1. 拆除了一个会导致系统崩溃的“核弹级”Bug。
  2. 作为性能优化(引入红黑树)过程中的一个必然修复。
  3. 降低了误用HashMap时带来的风险,使框架更健壮。

面试官问这个问题,就是想考察你是否理解技术决策背后的权衡和深层原因,而不仅仅是背诵“1.7是头插法,1.8是尾插法和红黑树”。

正确的并发选择:在需要保证线程安全的场景下,我们应该始终使用 ConcurrentHashMap

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/88380.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/88380.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/88380.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI技术正以前所未有的速度重塑职业生态与行业格局,尤其在自动化测试领域,AI驱动的测试框架通过智能化、低代码化重构传统测试流程。

AI技术正以前所未有的速度重塑职业生态与行业格局,尤其在自动化测试领域,AI驱动的测试框架通过智能化、低代码化重构传统测试流程。以下从职业影响、技术架构、行业应用及应对策略四个维度展开分析,结合代码示例与框架设计图解:一…

在 Mac 上安装 Java 和 IntelliJ IDEA(完整笔记)

目录 检查是否已安装 Java安装 Java(JDK)设置 JAVA_HOME 环境变量安装 IntelliJ IDEA配置 IntelliJ IDEA 使用 JDK验证和测试环境是否成功 1. 检查是否已安装 Java 打开终端(Terminal),输入: java -vers…

基于Java+Maven+Testng+Selenium+Log4j+Allure+Jenkins搭建一个WebUI自动化框架(2)对框架加入业务逻辑层

在上篇中,我们已经搭建好了框架的基本雏形,但只是引入了页面层、用例层的思想,我们在实际使用中会发现,如果我们很多的用例需要很多前置工作,这些前置工作又有可能涉及到多个页面,那么我们在维护的时候就会…

uniapp ruoyi-app 中使用checkbox 无法选中问题

<view class"flex align-center"> <checkbox-group> <label> <checkbox value"cb" checked"true" /> 记住密码 </label> </checkbox-group> </view>colorui.css 文件中注释掉两处即可全局搜索…

如何快速学习GO语言

https://go.dev/tour/welcome/1 这个是官方的引导&#xff0c;很实用基本重点内容都涵盖了&#xff0c;并且可以一边学习一边练习&#xff0c;非常好用 简单介绍一下&#xff1a; Hello, 世界 欢迎访问 Go 编程语言教程。 本教程分为几个模块&#xff0c;点击本页左上角的 …

AI 产品经理必看:神秘技术架构图如何打通跨团队沟通壁垒?

​ 你好&#xff0c;我是 三桥君 引言 在AI产品的开发过程中&#xff0c;技术架构图是连接业务需求与技术实现的桥梁。然而&#xff0c;许多AI产品经理常常面临以下挑战&#xff1a;研发团队认为需求描述不清晰&#xff0c;业务团队与技术团队沟通不畅&#xff0c;技术选型时…

【科研绘图系列】R语言绘制解剖图

文章目录 介绍加载R包数据下载导入数据数据预处理画图系统信息参考介绍 【科研绘图系列】R语言绘制解剖图 加载R包 # install.packages("devtools") # library(devtools) # devtools::install_github("jespermaag/gganatogram")library(gganatogram) li…

【unity编辑器开发与拓展EditorGUILayoyt和GUILayoyt】

EditorGUILayout 与 GUILayout 的核心区别及使用场景详解 一、对比表特性GUILayoutEditorGUILayout命名空间UnityEngineUnityEditor使用场景运行时 UI 编辑器扩展仅限编辑器扩展控件风格基础游戏风格&#xff08;无编辑器优化&#xff09;原生 Unity 编辑器风格布局复杂度基础…

【数据结构】8. 二叉树

文章目录一、树的概念及结构1、树的概念2、树的相关概念3、树的表示4、树的实际运用二、二叉树的概念及结构1、二叉树的概念2、特殊的二叉树3、二叉树的性质4、二叉树的存储结构三、二叉树的顺序结构及实现1、二叉树的顺序结构2、堆的概念及结构3、堆的实现0&#xff09;准备工…

Spring MVC中异常处理

1.全局异常处理1.1什么是全局异常处理器全局异常处理器是SpringMVC框架中的一种异常处理机制&#xff0c;用于统一处理由控制器抛出的异常。全局异常处理器可以帮助我们捕获和处理控制器中的异常&#xff0c;并且根据不同的异常类型进行不同的处理操作&#xff0c;从而保障应用…

imx6ull-系统移植篇2—— U-Boot 命令使用(上)

目录 前言 U-Boot 命令 help 信息查询命令 bdinfo printenv version 环境变量操作命令 setenv 和 saveenv 修改环境变量 新建环境变量 删除环境变量 内存操作命令 md nm mm mw cp cmp 网络操作命令 ping 命令 dhcp 命令 nfs 命令 tftp 命令 EMMC 和 S…

vector之动态二维数组的底层

引言&#xff1a;在计算机编程领域&#xff0c;二维动态数组是一种能够在程序运行期间动态调整其大小的二维数组数据结构。它与静态二维数组的关键区别在于&#xff0c;静态二维数组在编译时就需要确定其大小&#xff0c;而二维动态数组的大小可以在程序运行过程中根据实际需求…

第十六天,7月10日,八股

1、mybatis的延迟加载需要时才加载关联对象&#xff0c;而不是查询主对象时&#xff0c;立刻加载所有关联对象&#xff0c;这样可以提高查询性能并减少不必要的数据库访问&#xff0c;例如&#xff1a;一个订单表包含着商品列表&#xff08;一对多&#xff09;&#xff0c;当查…

CSS中的Element语法

1.1 Element语法1.1.1 案例 1. 快速生成10个div,并且每个div里面是从1到10的内容2.生成一个div标签&#xff0c;类名为one,并且同时生成一个id为first的p标签1.1.2 快速生成CSS样式语法 CSS基本采取简写形式即可 比如w22 按住tab键 可以生成 width:200px比如lh26px 按住tab键 可…

Go从入门到精通(21) - 一个简单web项目-添加swagger文档

Go从入门到精通(20)-一个简单web项目-服务搭建 文章目录Go从入门到精通(20)-一个简单web项目-服务搭建前言前期准备为API 添加 Swagger 文档1.安装依赖2.添加 Swagger 注释main.goapp.goapi.gopublic_handler.goauth_handler.gocommon_constant.gocommon_dto.gotoken_utils.go3…

自动驾驶环境感知:天气数据采集与融合技术实战

天气与我们日常各类生活场景密不可分&#xff0c;在驾驶场景里当车主发动汽车准备驶向目的地时&#xff0c;窗外的阴晴或许只是直观感受&#xff0c;而真正影响驾驶安全与行程效率的&#xff0c;可能是几公里外的突发暴雨、桥面的结冰预警&#xff0c;或是前方路段的强侧风等级…

基于svga+uniapp的微信小程序动画组件开发指南

lottie动画指南 效果 概述 本项目使用 svgaplayer.weapp.js 库来实现 SVGA 动画播放功能&#xff0c;支持在微信小程序、H5 等多端环境下播放高质量的矢量动画。SVGA 是一种跨平台的开源动画格式&#xff0c;具有文件小、渲染性能高的特点。 技术栈 核心库: svgaplayer.wea…

数据结构与算法——计算直线的交点数

前言&#xff1a; 这是之前做的一道笔试题&#xff0c;当时没写出来烦恼很久&#xff0c;这次记录一下。 题目链接&#xff1a; Dotcpp--题目 1174: 计算直线的交点数 参考文章&#xff1a; CSDN--槐阳7--计算直线的交点数 题目&#xff1a; 解题思考&#xff1a; 在当时…

大模型及agent开发6 OpenAI Assistant API 高阶应用 - 流式输出功能

1.Assistant API 的主要优点&#xff1a; 减少编码工作量、自动管理上下文窗口、安全的访问控制、工具和文档的轻松集成 本节讲应用设计和性能流式输出&#xff1a;借助流式输出&#xff0c;可以让应用程序实时处理和响应用户输入。具体来说&#xff0c;这种技术允许数据在生成…

React Native安卓刘海屏适配终极方案:仅需修改 AndroidManifest.xml!

&#x1f4cc; 问题背景在 React Native 开发中&#xff0c;我们经常会遇到安卓设备刘海屏&#xff08;Notch&#xff09;适配问题。即使正确使用了 react-native-safe-area-context 和 react-navigation&#xff0c;在一些安卓设备&#xff08;如小米、华为、OPPO 等&#xff…