论坛
潜水/灌水快乐,沉淀知识,认识更多同行。
ToB圈子
加入IT圈,遇到更多同好之人。
朋友圈
看朋友圈动态,了解ToB世界。
ToB门户
了解全球最新的ToB事件
博客
Blog
排行榜
Ranklist
文库
业界最专业的IT文库,上传资料也可以赚钱
下载
分享
Share
导读
Guide
相册
Album
记录
Doing
应用中心
搜索
本版
文章
帖子
ToB圈子
用户
免费入驻
产品入驻
解决方案入驻
公司入驻
案例入驻
登录
·
注册
账号登录
立即注册
找回密码
用户名
Email
自动登录
找回密码
密码
登录
立即注册
首页
找靠谱产品
找解决方案
找靠谱公司
找案例
找对的人
专家智库
悬赏任务
圈子
SAAS
qidao123.com技术社区-IT企服评测·应用市场
»
论坛
›
软件与程序人生
›
后端开发
›
Java
›
Java 线程安全的聚集
Java 线程安全的聚集
用户国营
论坛元老
|
2025-3-11 17:23:55
|
显示全部楼层
|
阅读模式
楼主
主题
1773
|
帖子
1773
|
积分
5319
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要
登录
才可以下载或查看,没有账号?
立即注册
x
Vector
ArrayList 的线程安全版本,对全部的修改方法都进行了 synchronized 同步处理。适用于多线程环境下对数据一致性要求高,且读写操作相对比较平衡,不需要很高并发性能的场景。由于全部操作都进行同步,在高并发环境下,性能相对较差
Hashtable
HashMap 的线程安全版本,对每个关键方法都进行了 synchronized 同步处理。在多线程环境下需要一个线程安全的键值对存储结构,而且对数据的读写频率相对平衡时适用。高并发下性能不佳,而且不允许键或值为 null
ConcurrentHashMap
1. 数据结构
在 JDK1.7 中,ConcurrentHashMap 底层数据结构由多个 Segment 构成,Segment 继承自 ReentrantLock,本质上是一个可重入锁,每个 Segment 独立管理一部分数据,相称于一个小型的哈希表。每个 Segment 内部包罗一个 HashEntry 数组,用于存储键值对。HashEntry 是一个链表结构,用于解决哈希冲突,新的键值对会插入到链表头部
在 JDK1.8 中,ConcurrentHashMap 底层数据结构是一个 Node 数组,Node 节点用链表或红黑树解决哈希冲突。当链表长度小于等于 8 时,采用链表存储数据。当链表长度大于 8 且数组长度大于 64 时,链表会转化为红黑树
2. 读取原理
在 JDK1.7 中,HashEntry 的 value 和 next 指针都被声明为 volatile 类型,保证内存可见性。差别的 Segment 可以并发访问,多个线程可以同时读取差别 Segment 的数据
在 JDK1.8 中,Node 节点的 value 和 next 指针都被声明为 volatile 类型,保证内存可见性。多个线程可同时读取差别位置的元素,提高并发读性能
3. 写入原理
在 JDK1.7 中,起首需要根据键的哈希值定位到对应的 Segment,然后获取该 Segment的锁。获取锁后,在对应 Segment 的 HashEntry 数组中找到符合的位置,将新的键值对插入到链表头部
在 JDK1.8 中,起首需要根据键的哈希值定位到对应的 Node 数组索引,若该位置为空,使用 CAS 操作将新节点插入,成功则插入完成。若 CAS 插入失败,说明发生哈希冲突。当发生哈希冲突时,若是链表,则对链表头节点加锁,遍历链表插入或更新,若是红黑树,则对红黑树的根节点加锁,按红黑树规则插入或更新
4. 扩容机制
在 JDK1.7 中,当某个 Segment 的 HashEntry 数组的元素数量达到阈值时,该 Segment 会加锁进行扩容操作。扩容时会创建一个新的更大的 HashEntry 数组,然后将原数组中的元素重新哈希并复制到新数组。差别的 Segment 可以独立进行扩容,不会影响其他 Segment 的正常操作
在 JDK1.8 中,当元素数量达到阈值,触发扩容。起首使用 CAS 操作创建一个更大的 Node 数组,然后使用 CAS 操作更新数组中的 Node 节点引用,再对 Node 节点的链表头节点或红黑树根节点使用 synchronized 关键字加锁,进行数据迁移操作。ConcurrentHashMap 采用多线程分段迁移的方式将原数组元素迁移到新数组,差别线程可负责差别段的迁移工作
CopyOnWriteArrayList / CopyOnWriteArraySet
CopyOnWriteArrayList 是一种线程安全的 List 实现,允许在多线程环境下进行并发的读写操作,其核心头脑是“写时复制”,即当进行写操作时,会创建一个原数据结构的副本,在副本上进行修改,完成后再将副本更换原数据结构。CopyOnWriteArraySet 与 CopyOnWriteArrayList 的作用与实现类似
当执行写操作时,CopyOnWriteArrayList 会先创建一个当前数组的副本,对副本进行写操作。由于操作的是副本,不会影响到其他线程对原数组的读操作,从而保证了读写之间的并发安全。完成对副本的写操作后,会通过原子操作将原数组的引用更换为指向新的副本数组的引用。在这个更换过程中,使用 volatile 关键字修饰数组引用,保证其他线程可以或许实时看到更新后的数组。上述整个过程使用 ReentrantLock 锁保证同一时候只有一个线程可以或许进行写操作
ConcurrentLinkedQueue
ConcurrentLinkedQueue 是基于链表实现的线程安全队列,采用 CAS 算法实现无锁的并发访问。比如多个线程同时进行出队操作时,每个线程都可以独立地实验更新头节点的引用,通过 CAS 操作确保只有一个线程可以或许成功更新,从而实现了无锁的并发访问
BlockingQueue
BlockingQueue 是壅闭队列,内部使用锁机制实现线程安全。当队列已满时,实验向队列中添加元素的线程会被壅闭,直到队列有空间可用。当队列为空时,实验从队列中获取元素的线程会被壅闭,直到队列有元素可获取
具体参考:
https://www.cnblogs.com/Yee-Q/p/14580034.html
同步包装器
Java 同步包装器是指通过 Collections 类的静态方法将非线程安全的聚集转换为线程安全的聚集,主要包括以下几种:
synchronizedList:把普通的 List 转换为线程安全的列表。通过对 List 的全部操作添加同步锁,确保同一时候只有一个线程可以或许访问列表,克制并发访问时出现数据不一致等问题,如 List synchronizedList = Collections.synchronizedList(new ArrayList());
synchronizedMap:把普通的 Map 转换为线程安全的映射。在对 Map 进行操作时,都会进行同步处理,保证多线程环境下 Map 的操作安全,如:Map synchronizedMap = Collections.synchronizedMap(new HashMap());
synchronizedSet:把普通的 Set 转换为线程安全的聚集。通过同步机制,确保在多线程访问 Set 时,元素的添加、删除等操作不会出现并发问题,如:Set synchronizedSet = Collections.synchronizedSet(new HashSet());
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复
使用道具
举报
0 个回复
正序浏览
返回列表
快速回复
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
or
立即注册
本版积分规则
发表回复
回帖并转播
发新帖
回复
用户国营
论坛元老
这个人很懒什么都没写!
楼主热帖
Beta 阶段事后分析
iOS全埋点解决方案-APP和H5打通 ...
Android studio实现网上订餐app
Ubuntu22.04+ROS2中实现Moveit2控制gaz ...
关键容灾技能比较
完整版彻底卸载SQL Server2019
一键设置 Docker 环境:具体指南与最佳 ...
mysql主从搭建
复杂「场景」数据导入导出
分布式锁
标签云
渠道
国产数据库
集成商
AI
运维
CIO
存储
服务器
快速回复
返回顶部
返回列表