首页 > 编程语言 >JUC并发编程第十四章——线程安全集合类

JUC并发编程第十四章——线程安全集合类

时间:2024-06-19 11:30:37浏览次数:15  
标签:bin JUC HashMap 编程 安全 线程 Hashtable 集合

1 并发集合

1.1 线程安全集合分类

a.遗留的线程安全集合

  • 遗留的线程安全集合如 Hashtable , Vector

b.使用 Collections 装饰的线程安全集合

  • 使用 Collections 装饰的线程安全集合,如:
    • Collections.synchronizedCollection
    • Collections.synchronizedList
    • Collections.synchronizedMap
    • Collections.synchronizedSet
    • Collections.synchronizedNavigableMap
    • Collections.synchronizedNavigableSet
    • Collections.synchronizedSortedMap
    • Collections.synchronizedSortedSet
  • java.util.concurrent.*

c.JUC下的安全集合: Blocking、CopyOnWrite、Concurrent

重点介绍 java.util.concurrent.* 下的线程安全集合类,可以发现它们有规律,里面包含三类关键词: Blocking、CopyOnWrite、Concurrent

  • Blocking类型 大部分实现基于锁,并提供用来阻塞的方法。该类中大部分方法都是在不满足条件时进行阻塞等待。
  • CopyOnWrite类型 之类容器修改开销相对较重。采用了一种在修改时拷贝的方式来避免多线程访问读写时的线程安全问题。适用于读多写少的情况 (写的开销相对比较大)。
  • Concurrent 类型的容器 (性能较高)
    • 优点:内部很多操作使用 cas 优化,一般可以提供较高吞吐量
    • 缺点:弱一致性
      • 遍历时弱一致性,例如,当利用迭代器遍历时,如果容器发生修改,迭代器仍然可以继续进行遍历,这时内容是旧的
      • 求大小弱一致性,size 操作未必是 100% 准确
      • 读取弱一致性

遍历时如果发生了修改,对于非安全容器来讲,使用 fail-fast 机制也就是让遍历立刻失败,抛出ConcurrentModifificationException,不再继续遍历


1.2 集合对比

三种集合:

  • HashMap 是线程不安全的,性能好
  • Hashtable 线程安全基于 synchronized,方法被synchronized修饰,虽然能保证线程安全,但性能太差,已经被淘汰
  • ConcurrentHashMap 保证了线程安全,综合性能较好,不止线程安全,而且效率高,性能好

注意:修饰的安全集合类,如:SynchronizedMap,本质和Hashtable类一样,都是在每个方法上加了一个sychronized关键字修饰,性能上仍然没什么提升,因此也不推荐。

集合对比:

  1. Hashtable 继承 Dictionary 类,HashMap、ConcurrentHashMap 继承 AbstractMap,均实现 Map 接口
  2. Hashtable 底层是数组 + 链表,JDK8 以后 HashMap 和 ConcurrentHashMap 底层是数组 + 链表 + 红黑树
  3. HashMap 线程非安全,Hashtable 线程安全,Hashtable 的方法都加了 synchronized 关来确保线程同步
  4. ConcurrentHashMap、Hashtable 不允许 null 值,HashMap 允许 null 值
  5. ConcurrentHashMap、HashMap 的初始容量为 16,Hashtable 初始容量为11,填充因子默认都是 0.75,两种 Map 扩容是当前容量翻倍:capacity * 2,Hashtable 扩容时是容量翻倍 + 1:capacity*2 + 1

ConcurrentHashMap数据结构

工作步骤:

  1. 初始化,使用 cas 来保证并发安全,懒惰初始化 table

  2. 树化,当 table.length < 64 时,先尝试扩容,超过 64 时,并且 bin.length > 8 时,会将链表树化,树化过程会用 synchronized 锁住链表头

    说明:锁住某个槽位的对象头,是一种很好的细粒度的加锁方式,类似 MySQL 中的行锁

  3. put,如果该 bin 尚未创建,只需要使用 cas 创建 bin;如果已经有了,锁住链表头进行后续 put 操作,元素添加至 bin 的尾部

  4. get,无锁操作仅需要保证可见性,扩容过程中 get 操作拿到的是 ForwardingNode 会让 get 操作在新 table 进行搜索

  5. 扩容,扩容时以 bin 为单位进行,需要对 bin 进行 synchronized,但这时其它竞争线程也不是无事可做,它们会帮助把其它 bin 进行扩容

  6. size,元素个数保存在 baseCount 中,并发时的个数变动保存在 CounterCell[] 当中,最后统计数量时累加


2 ConcurrentHashMap

标签:bin,JUC,HashMap,编程,安全,线程,Hashtable,集合
From: https://blog.csdn.net/qq_64064246/article/details/139790922

相关文章

  • C#/.Net 中的多线程介绍和最佳实践
    I/引言计算机中的线程CPU调度程序和时间切片进程和线程并发和并行性异步与多线程在C中使用多线程的好处#II线程C语言#线程生命周期创建、启动和暂停线程加入中止中断线程取消:停止线程的更好方法III/线程问题死锁和争用条件使用Join和LocksAutoRese......
  • 【信息学奥赛】CSP-J/S初赛03 计算机网络与编程语言分类
    第1节计算机网络基础1.1网络的定义所谓计算机网络,就是利用通信线路和设备,把分布在不同地理位置上的多台计算机连接起来。计算机网络是现代通信技术与计算机技术相结合的产物。网络中计算机与计算机之间的通信依靠协议进行。协议是计算机收、发数据的规则。TCP/IP:用于......
  • 《 Python趣味编程 | 从入门到就业》专栏介绍
    前言欢迎订阅《Python趣味编程|从入门到就业》专栏!本专栏主要包含六大部分:⭐Python炫酷系列⭐Python动漫系列⭐Python游戏系列⭐Python基础知识⭐Python实用技巧⭐Python算法设计【注】订阅后可查看专栏内所有文章。(含完整代码+详细解析+资源下载链接)环境配置​P......
  • IPython:交互式Python编程环境的详解
    文章目录引言安装IPythonIPython的基本使用启动IPython输入和执行代码自动补全历史记录交互式帮助IPython的高级功能魔术命令(MagicCommands)%lsmagic和%magic%pdb和%debug%who和%whos%time和%timeit%run%edit丰富的输出格式交互式绘图面向对象编程和自省......
  • python编程笔记
    pythonimport库失败:原因是解释器选择不对,pip3installnumpy是把numpy库安装在3.xxx的python解释器中,但是我是在3.9.6的解释器下运行的,所以找不到,此时需要把解释器换成3.11.9即可。Super(Net,self)._init_()这是对继承自父类的属性进行初始化,子类继承了父类的所有属性......
  • Shell编程之循环语句
    Shell编程之循环语句一、for循环语句for语句的结构for语句应用示例二、while循环语句while语句的结构while语句应用示例三、until循环语句until语句结构until语句应用示例注意:在Shell编程中,循环语句是一个非常重要的组成部分,它允许我们重复执行某段代码,直到满......
  • C#图形图像编程
    一.实验目标和实验内容:掌握C#图形绘制基本概念;掌握C#字体处理;能进行C#图形图像综合设计。运行效果如下所示:二.准备(1)创建一个新项目:(2)在工具箱中拖出四个控件,button1,button2,panel,textbox(可单击控件在右下角修改名字)三.代码实现(1)button1privatevoidbutton1_Click(ob......
  • 线程的状态,中断及守护线程
    线程的状态在Java程序中,一个线程对象只能调用一次start()方法启动新线程,并在新线程中执行run()方法。一旦run()方法执行完毕,线程就结束了。因此,Java线程的状态有以下几种:New:新创建的线程,尚未执行;Runnable:运行中的线程,正在执行run()方法的Java代码;Blocked:运行中的线程,因为某......
  • 在现代编程环境中,Perl 如何与其他流行语言(如 Python、Java 等)进行集成和协作?
    在现代编程环境中,Perl可以与其他流行语言(如Python、Java等)进行集成和协作。以下是一些常见的方法:调用外部程序:Perl可以使用系统调用来执行其他语言编写的可执行文件。这意味着可以从Perl中调用Python、Java等程序,并将它们的输出捕获到Perl程序中进行处理。使......
  • 程序分享--常见算法/编程面试题:判断子序列
    关注我,持续分享逻辑思维&管理思维&面试题;可提供大厂面试辅导、及定制化求职/在职/管理/架构辅导;推荐专栏《10天学会使用asp.net编程AI大模型》,目前已完成所有内容。一顿烧烤不到的费用,让人能紧跟时代的浪潮。从普通网站,到公众号、小程序,再到AI大模型网站。干货满满。学成后可......