Java多线程八股(三)一>多线程环境使用哈希表和ArrayList

目录:

一.多线程环境使用ArrayList:

二.多线程使用哈希表:

一.多线程环境使用ArrayList:

首先我们知道,Vector, Stack, HashTable, 是线程安全的(但是不建议用), 其他的集合类不是线程安全的 ,下面是 ArrayList的使用场景
1.自行对代码加锁 (推荐使用)


2. 套个壳使用Collections.synchronizedList(new ArrayList)

就类似于上面的HashTable这些,但是不推荐使用因为使用加锁是有代价的(性能开销等等)
synchronizedList 是标准库提供的一个基于 synchronized 进行线程同步的 List. synchronizedList的关键操作方法上都带有 synchronized


3.使用 CopyOnWriteArrayList容器:

这个容器不是加锁设计的,而是用编程常见的一种思想方法->写时拷贝

以下是 写时拷贝的讲解:
注意:CopyOnWriteArrayList容器也不是所有场景都适合,当数组非常大和涉及多个线程修改时就会可能出错



二.多线程使用哈希表:
HashMap 本身不是线程安全的
在多线程环境下使用哈希表可以使用: Hashtable ConcurrentHashMap


1.Hashtable
只是简单的把关键方法加上了 synchronized 关键字,(相当给this加锁,就是给整个哈希表加锁)
这样如果修改两个元素 不在同一个链表上,就是修改不同元素 不会发生线程安全问题
但是如果在同一个链表上就可能会发生线程安全问题 (比如把两个元素插入到第一个元素后面)



2.ConcurrentHashMap:
(1). 读操作没有加锁(但是使用了 volatile 保证从内存读取结果)


(2). 只对写操作进行加锁. 加锁的方式仍然是是⽤ synchronized, 但是不是锁整个对象, 而是"锁桶" (用每个链表的头结点作为锁对象), 大大降低了锁冲突的概率.


(3).充分利用CAS(原子类)特性. 比如 size 属性通过 CAS 来更新. 避免出现重量级锁的情况也避免了线程安全问题. (通过原子类修饰size)


(4).优化了扩容方式: 化整为零
化整为零解释:
扩容需要把旧的哈希表元素全部搬运一次性搬运到新的哈希表,这个时候如果元素太多搬运完,势必进行更长时间的加锁解锁,会很耗时间,这个时候就可以采用"化整为零"的方式,不是一次搬运完,而是多次进行搬运(一次搬运百分之几),后续再进行基本操作,这样加锁解锁耗时就很短,分多次部分触发完成全部任务

相关推荐
“AI国潮设计-小江”7 分钟前
【Python/SDXL实战】潮汕国潮IP视觉落地:普宁英歌舞猫IP & 创意甜品设计(附ComfyUI工作流与商业授权说明)
开发语言·人工智能·python·prompt·aigc
529宝宝起名网15 分钟前
用 Python 分析汉字字源与起名用字的关联规律:从六书结构到文化寓意的起名偏好洞察
开发语言·python
linx29523 分钟前
单元九 · 零基础路线图-第 7–9 周·类与 RAII
c语言·开发语言·数据结构·c++·嵌入式硬件·算法
砚底藏山河1 小时前
容错重试与指数退避:网络抖动手抖不再丢数据(魔码量化实战 #04)
java·数据库·python·金融
白色的北极熊1 小时前
c语言 输出菱形字符串
c语言·开发语言
2501_930472441 小时前
云安全自查清单:用腾讯云助手 30 分钟完成一次权限与密钥体检
java·腾讯云
学习智者2 小时前
《玄》IDE v3.6.3重磅发布:全功能修复与性能飞跃
开发语言·c++·ide·算法·中文语言 玄
奔跑吧树袋熊2 小时前
多租户隔离该做到哪一层:从连接池到 ORM 的取舍
开发语言·数据库·oracle·系统架构
letisgo52 小时前
JAVA 高级进阶05篇《Spring容器机制:Bean生命周期与三级缓存全解》
java·spring·面试·ioc·源码分析
岁月如歌77862 小时前
分布式锁完全指南:从数据库到 Redisson 的演进
java·后端·架构