javaEE 初阶 — 线程安全的集合类

news2025/1/16 6:40:23

文章目录

  • 1. 多线程环境使用 ArrayList
  • 多线程使用队列
  • 3. 多线程环境使用哈希表
    • 3.1 Hashtable
    • 3.2 ConcurrentHashMap
  • 4. 相关面试题

1. 多线程环境使用 ArrayList


java 标准库里的大部分集合类都是 “线程不安全” 的。
多个线程使用同一个集合类对象,很有可能会出问题。

VectorStackHashTable,是线程安全的(不建议用),其他的集合类不是线程安全的。

1、自己加锁,自己使用 synchronized 或者 ReentrantLock


2、Collections.synchronizedList 这里会提供一些 ArrayList 相关的方法,同时是带锁的。


3、使用 CopyOnWriteArrayList

简称为 COW ,也叫做 “写时拷贝” 。

如果针对这个 ArrayList 进行读操作,不作任何额外的工作。

如果进行写操作,则拷贝一份新的 ArrayList ,针对新的进行修改,修改过程中如果有读操作,就继续旧的这份数据。
当修改完毕了,使用新的替换旧的(本质上就是一个引用之间的赋值,原子的

这种方案的优点是 不需要加锁;缺点是 要求这个 ArrayList 不能太大
只适用于数组比较小的情况。

多线程使用队列

\

3. 多线程环境使用哈希表


HashMap 是线程不安全的,HashTable 是线程安全的(内部给关键方法加上了synchronized

但是更推荐的是:ConcurrentHashMap ,这是更优化的线程安全哈希表。

3.1 Hashtable


Hashtable 的做法是直接在方法上加 synchronized ,等于是给 this 加锁。
只要操作哈希表上的任意元素,都会产生加锁,也就都会发生锁冲突。

但是实际上仔细思考不难发现,其实基于哈希表的结构特点有些元素在进行并发操作的时候,
是不会产生线程安全问题的,也就不需要使用锁控制。



此时元素 1 和 2 在同一个链表上。
如果线程A修改元素 1 ,线程 B 修改元素 2 ,是否有线程安全问题?(修改可能包含 增删改

这个情况是需要加锁的,比如这两个元素相邻,此时并发的插入或者删除,就要修改这两个结点相邻的结点的 next 的指向。



如果线程 A 修改元素 3 ,线程 B 修改元素 4 是否有线程安全问题呢?

这个情况是不需要加锁的,这时就相当于多个线程修改不同的变量。

HashMap 锁冲突概率太大了,任何两个元素都会有锁冲突,即使是处在不同的链表上。
(这是不用 HashMap 的最主要原因)

3.2 ConcurrentHashMap


ConcurrentHashMap 进行了哪些优化?比 Hashtable 好在哪里?和 Hashtable 之间的区别是什么?

1、最大的优化之处:ConcurrentHashMap 相比于 Hashtable 大大缩小了锁冲突的概率
可以理解为把一把大锁转换成了多把小锁。

ConcurrentHashMap 的做法是每个链表有各自的锁,而不是大家共用一个锁。

具体来说就是使用每个链表得头结点作为锁对象。
(两个线程针对同一个锁对象加锁,才会有阻塞等待,针对不同对象,没有锁竞争)



此时锁的粒度变小了。
针对 1 2 这个情况,是针对同一把锁进行加锁。会有锁竞争,会保证线程安全。
针对 3 4 这个情况,是针对于不同的锁进行加锁。不会有锁竞争,没有阻塞等待,程序就会更快。
(这是相对的快,但是不回比加锁快)


2、ConcurrentHashMap 做了一个激进的操作

针对读操作,不加锁,只针对写操作加锁。

读和读之间没有冲突,读和写之间也没有冲突,写和写之间有冲突。
很多场景下,读写之间不加锁控制,可能会读到一个写了一半的结果,如果写操作不是原子的,此时读就可能会读到写了一半的锁,相当于是脏读了。


3、ConcurrentHashMap 内部充分的使用了 CAS ,通过这个也来进一步的消减加锁操作的数目

比如维护元素个数。


4、针对扩容,采取了 化整为零 的方式

HashMap 或者 HashTable 扩容:

创建一个更大的数组空间,把旧的数组上的链表上的每个元素搬运到新的数组上。(删除 + 插入)
这个扩容操作会在某次 put 的时候进行触发。
如果元素的个数特别多,就会导致这样的搬运操作比较耗时。
就会出现某次 put 的时候比平时的 put 卡好多倍。

ConcurrentHashMap 中采取的扩容方式是每次搬运一小部分元素的方式。
创建新的数组,旧的数组也保留。
每次 put 操作,都会往新数组上添加,同时进行一部分的搬运(把一部分旧的元素搬运到新数组上)
每次 get 的时候,则是旧数组和新数组都查询。
每次 remove 的时候,只是把元素删了就行了。
经过一段时间后,所有的元素都搬运好了,最终再释放旧数组。

4. 相关面试题


1、ConcurrentHashMap的读是否要加锁,为什么?

读操作没有加锁,目的是为了进一步降低锁冲突的概率。
为了保证读到刚修改的数据,搭配了volatile 关键字。


2、介绍下 ConcurrentHashMap的锁分段技术?

这个是 Java1.7 中采取的技术。Java1.8 中已经不再使用了。
简单的说就是把若干个哈希桶分成一个"段" (Segment),针对每个段分别加锁。

目的也是为了降低锁竞争的概率,当两个线程访问的数据恰好在同一个段上的时候,才触发锁竞争。




3、ConcurrentHashMap在jdk1.8做了哪些优化?

取消了分段锁,直接给每个哈希桶(每个链表)分配了一个锁(就是以每个链表的头结点对象作为锁对
象)。

将原来 数组 + 链表 的实现方式改进成 数组 + 链表 / 红黑树 的方式。
当链表较长的时候(大于等于8 个元素)就转换成红黑树。


4、Hashtable和HashMap、ConcurrentHashMap 之间的区别?

HashMap:

线程不安全,key 允许为 null。

Hashtable:

线程安全,使用 synchronized 锁 Hashtable 对象,效率较低,key 不允许为 null。

ConcurrentHashMap:

线程安全,使用 synchronized 锁每个链表头结点,锁冲突概率低,充分利用CAS 机制。优化了扩容方式,key 不允许为 null。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

WebDAV之葫芦儿·派盘+Air Explorer

Air Explorer 支持WebDAV方式连接葫芦儿派盘。 电脑本地硬盘不够,网盘云存储已经成为存储的一种趋势。网盘限额,数据存在多个网盘内,操作麻烦还费事。 Airexplorer可以完美解决这个困扰。Air Explorer是一款非常不错的云存储账户管理软件,常见的在线云存储服务器都支持;还…

六道算法基础题详解

目录 1.力扣第217题:存在重复元素 2.力扣第53题:最大子数组和 3.力扣第1题:两数之和 4.力扣第88题:合并两个有序数组 5.牛客BM1题:反转链表 6.牛客BM2题:链表内指定区间反转 1.力扣第217题&#xff1…

6.1、应用层概述

1、基本概述 应用层是计算机网络体系结构的最顶层\color{red}最顶层最顶层,是设计和建立计算机网络的最终目的\color{red}设计和建立计算机网络的最终目的设计和建立计算机网络的最终目的,也是计算机网络中发展最快的部分。 早期基于文本的应用(电子邮件…

RNNoise:学习噪声抑制

目录 1. RNNoise简介 2. 噪声抑制 3. 深度学习和循环神经网络 4. 一种混合的方法 6. 关于数据集 7. 从python到C语言 8. 其他资源 RNNoise:学习噪声抑制 原文地址:RNNoise: Learning Noise Suppression (jmvalin.ca) 1. RNNoise简介 该例子展示…

共享购深度解析——新玩法解读

共享经济模式以合理配置网络资源、减少销售市场交易费用、推动私营经济强势来袭等优点颠覆性创新地严重影响传统商业模式,根据“自由者”的协同,共享经济模式给供需彼此更自由选择和由上而下的制度变革,提高了经济形势高效率,变成…

Pytorch 环境和分布偏移与错误使用机器学习例子

假设我们训练了一个贷款申请人违约风险模型,用来预测谁将偿还贷款或违约。 这个模型发现申请人的鞋子与违约风险相关(穿牛津鞋申请人会偿还,穿运动鞋申请人会违约)。 此后,这个模型可能倾向于向所有穿着牛津鞋的申请人…

代码随想录算法训练营第十六天二叉树 java : 104.二叉树的最大深度 111.二叉树的最小深度 222.完全二叉树的节点个数

文章目录前言深度是个啥,高度又是啥Leetcode 104.二叉树的最大深度题目讲解Leetcode 111.二叉树的最小深度题目讲解Leetcode 222.完全二叉树的节点个数(优先掌握递归题目讲解总结前言 今天将主要围绕 深度和高度 来展开 复习一下递归三部曲 确定递归函…

已解决微软Office2016 Excel卡顿\缓慢、打开第二个文件加载很慢问题(亲测有效)

已解决微软Office2016 Excel卡顿\缓慢、打开第二个文件加载很慢问题(亲测有效) 文章目录问题描述问题分析解决方法1解决方法2解决方法31) 修改基本设置2)修改配置文件问题描述 我的电脑环境是:Windows 10 Excel 2016版本。 文件…

【前端之旅】Nginx快速入门

一名软件工程专业学生的前端之旅,记录自己对三件套(HTML、CSS、JavaScript)、Jquery、Ajax、Axios、Bootstrap、Node.js、Vue、小程序开发(Uniapp)以及各种UI组件库、前端框架的学习。 【前端之旅】Web基础与开发工具 【前端之旅】手把手教你安装VS Code并附上超实用插件…

【Blender UV映射02】智能UV映射 创建和应用法线纹理

写在前面 前面的学习记录: 【Blende UV映射01】创建UV 使用UV贴图处理纹理 依旧是跟着Blender 2.8 UV Mapping教程,本文是教程的P8-P12的过程记录。 1 一些操作记录 调整滚轮缩放 如果发现Blender缩放过快, 键盘的"/"数字键…

Java并发编程实战 学习笔记 Day7

并发编程是比较进阶的知识,涉及到很多底层的东西,学习起来是比较困难的。并发编程的bug更多的是偶发性的,很难复现,排查起来也很困难,要想快速解决问题,就要理解并发编程的本质,追本溯源&#x…

Android ANR bugreport log分析

最近工作中频繁遇到设备ANR问题,而且是概率性的那种,于是决定花点时间找找规律复现分析下 说道这里,抓日志是问题解决的最有效途径,这里不得不说一下 bugreport log,其实网上关于它的分析方法有很多,在此仅仅是为了记录…

小型水库在线监测解决方案

一、方案背景水利部全国水利普查显示我国共有水库98002座,其中小型水库93308座。水库对防汛减灾、供水保障和农业灌溉等至关重要,水库的稳定运行关系到下游人民群众的生命财产安全,关系到当地经济发展和社会稳定。在2020年11月18日国务院常务…

EasyVim:简单强大的VIM配置

EasyVim 简单强大的vim配置,熟练后可大大提高开发效率(VS Code的两倍以上)。 安装 安装过程需要从github下载很多插件,国内尽量挂VPN git clone https://github.com/yuesong-feng/EasyVim cd EasyVim/ sh ./install.sh vim :P…

JavaScript基础(16)_数组方法、数组遍历、foreach

数组方法unshift():向数组开头添加一个或多个元素,并返回新的数组长度。向前边插入元素以后,其他的元素索引会依次调整。push():向数组的末尾添加一个或多个元素,并返回数组新的长度。该方法会将数组新的长度作为返回值返回。shift():删除数组…

【工具推荐】 Obsidian 插件 Obsidian to Flomo 一键同步内容到 Flomo 插件

目录一、Obsidian、Flomo、Obsidian to Flomo 他们都是什么?1. 什么是 Obsidian ?2. 什么是Flomo ?3. 什么是Obsidian to Flomo ?二、如何安装 Obsidian to Flomo ?三、插件使用方法1. 启用插件并配置API四、如何使用插…

《2022大数据产业年度创新技术突破》榜重磅发布丨金猿奖

‍年度金猿榜单/奖项本届“数据猿年度金猿策划活动——2022大数据产业创新技术突破榜单/奖项”由金猿&数据猿共同推出。‍数据智能产业创新服务媒体——聚焦数智 改变商业2022年下半年度,由数据猿、金猿组委会共同推出的第五届 “年度金猿季大型主题策划活动”…

Unity Netcode for GameObjects多人联机(源文件)

一、安装Netcode for Gameobjects Netcode for Gameobjects是Unity新推出的联机解决方案,该解决方案目前处于初期,相关功能不是很完善,但是用起来还不错。下面介绍一下相关用法。 首先下载安装Netcode for Gameobjects,其官方网站…

Elasticsearch入门介绍及Linux安装

前言Elasticsearch是一款分布式高性能的全文搜索引擎,为什么会需要这个呢,像我们平常使用的最多的存储工具就是Mysql,在业界也是非常有名的,我们大部分结构化数据都是用它来存储的,sql语言的操作也是非常方便&#xff…

助力“智慧港口”建设,北部湾港联合美创打造的主数据管理系统上线!

数字化浪潮下,港口企业发展将致力于以数据价值提升和数据价值创造为目标,打造新型“智慧港口”,实现更加经济的港口资源统筹高效利用并降低各类成本,企业通过逐步转变信息资源管理工作模式和利用方式,深度应用新一代信…