IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> Java软件开发 | 高并发编程篇之——安全访问的集合(1) -> 正文阅读

[数据结构与算法]Java软件开发 | 高并发编程篇之——安全访问的集合(1)

在开发中我们使用比较多的集合就是List、Set和Map了,并且我们也知道大部分用的基本上都是ArrayList、LinkedList、HashMap、HashSet或者TreeSet这几个集合。

但是我们在学习使用它们的时候都知道它们这几个在并发处理的时候并不会保证多线程的安全访问,也就是说多线程环境下使用这几个集合不能用于共享数据访问。

那有没有一些方法保证这些集合并发安全访问呢?

  1. Collections工具类并发的支持

其实java有一个叫做Collections的工具类提供了一些保证List、Set、Map线程安全方法的方法,如下图:

图片

其实通过其名称也不难猜想底层是使用了synchronized关键完成的同步代码块或者同步方法的实现。

其任意一个方法的源码如下(以List为例):

图片

图片

  1. 支持并发安全访问的集合

① ConcurrentHashMap

HashMap原理简介

我们知道HashMap的底层实现原理是分JDK1.7及其以前版本和JDK1.8版本的,JDK1.7及其以前HashMap是使用“数组+链表”组成的“散列桶”的实现,这个“桶”即为“数组”,默认容量为16,在每一个“桶”中存储了一个链表,但是链表一旦太长就会导致查找速度很慢(链表查找需要遍历),所以在JDK1.8的时候HashMap存储结构改为了当链表长度达到8之后(通过判断TREEIFY_THRESHOLD的值)将链表改为红黑二叉树的存储,这样对于数据操作的效率就大大提高了。

JDK8之后的HashMap如图:

图片

部分源码如下:

图片

图片

HashMap对其数据操作并没有做线程安全的处理,HashMap在其插入数据的时候都要进行容量检查看有没有超过设定的thredhold,如果超过,则需要扩容,但是这样一来,就需要对整个HashMap里的节点进行重哈希操作,那么如果现在多个线程访问HashMap数据那可能导致一个线程操作了之后HashMap进行哈希重新计算操作,另外一个线程读取到的就不准确,所以操作过程中并不是线程安全的。

ConcurrentHashMap原理简介

ConcurrentHashMap是J.U.C(java.util.concurrent包)的重要成员,它是一个线程安全却效率相对高效一些的类似HashMap的实现类。

ConcurrentHashMap 的实现同样也分为JDK7和JDK8版本。

JDK7及其之前底层采用是“数组+链表+Segment分段锁”的实现。其中Segment继承了ReentrantLock,这样ConcurrentHashMap 每个数组中的元素既是一个链表,又是一个Segment锁,使用Segment将访问的数据分成了一段一段的进行存储,因为每一个Segment都是一个锁所以相当于每一段数据也加了锁,这样就可以每一段锁支持一个线程访问,即保证了线程安全又降低了锁的粒度,大大提高了并发操作的效率。

图片

JDK8之后ConcurrentHashMap也同样参考了HashMap的设计,采用了“数组+链表+红黑树”的实现方式,但是却舍弃了“Segment分段锁”的设计(虽然JDK8的源码中还能够看到Segment类但是已经大大简化了代码设计主要为了JDK版本兼容设计)。

在JDK8的版本它存储的链表或者红黑树都使用了volatile关键字修饰,但是又因为volatile只是能保证线程的可见性和有序性不能够保证原子性操作,所以在进行put等操作的时候还使用了synchronized代码块处理。

部分核心源码如下图所示:

图片

图片

图片

它采用了synchronized 和 CAS(往期文章中有介绍CAS操作) 来替代JDK7的Segment分段锁的实现,JDK8中采用Synchronized关键字也是因为它在JDK6之后做了自旋、锁粗化、锁消除、锁升级等优化,另外对比于JDK7的Segment分段锁的是多个HashEntry,而JDK8锁的是单个的HashEntry粒度更小,效率更高。并且考虑到JDK可能对JVM底层synchronized关键字还会进行不断的优化所以JDK采用了synchronized的设计。

总的来说ConcurrentHashMap是我们在并发访问下的不错的HashMap的替换者。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-04-01 00:19:45  更:2022-04-01 00:22:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 9:58:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码