当前位置: 首页 > news >正文

多线程进阶——线程安全的集合类

目录

一、多线程环境使用ArrayList

(一)自行加锁

(二)Collections.synchronizedList(new ArrayList);

(三)使用 CopyOnWriteArrayList

二、多线程环境使用哈希表

(一)Hashtable

(二)ConcurrentHashMap


原来的集合类,大部分都不是线程安全的。

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

一、多线程环境使用ArrayList

(一)自行加锁

具体代码具体分析,要把那些代码打包到一起,成为一个“原子”操作。

(二)Collections.synchronizedList(new ArrayList);

synchronizedList 是标准库提供的一个基于 synchronized 进行线程同步的 List. synchronizedList

的关键操作上都带有 synchronized,从而实现原子类。

这是不推荐的,加锁有代价。

(三)使用 CopyOnWriteArrayList

CopyOnWrite容器即写时复制的容器,使用 CopyOnWriteArrayList就不用去加锁,运用到了“写时拷贝”的思想方法。

它的工作原理是:

  • 当我们往一个容器中添加元素时,不直接往这个容器里面添加,而是先将当前容器进行copy,复制出一个新的容器,然后往新的容器里面添加元素。
  • 添加完元素之后,再讲原容器的引用指向新的容器。

 

在多线程读取的时候,一旦某个线程进行写操作,比如修改 1 -> 100  
复制过程中,如果其他线程在读,就直接读取旧版本的数据  
虽然复制过程不是原子的(消耗一定的时间)  
由于提供了旧版本的数据,不影响其他线程读取  
新版本数组复制完毕之后,直接进行引用的修改。  
引用的赋值是“原子” 的,确保读取过程中,要么读到的是旧版数据,要么读到的是新版数据,不会读到“修改一半”的数据。 

二、多线程环境使用哈希表

HashMap本身不是线程安全的。

在多线程环境在使用哈希表可以使用:

  • Hashtable
  • ConcurrentHashMap

(一)Hashtable

Hashtable类中的各种public方法都加上了synchronized,这也相当于直接针对Hashtable对象本身加锁。

  • 如果多线程访问同一个 Hashtable 就会直接造成锁冲突.
  • size 属性也是通过 synchronized 来控制同步,也是比较慢的.
  • 一旦触发扩容,就由该线程完成整个扩容过程。这个过程会涉及到大量的元素拷贝,效率会非常低.

一个Hashtable只有一把锁,两个线程访问Hashtable中的任意数据都会出现锁竞争。

(二)ConcurrentHashMap

ConcurrHashMap根据Hashtable做出了一系列的改进和优化。

  • 读操作没有加锁,使用了volatile确保从内存中读取数据,只针对写操作进行加锁,但不是锁整个对象,而是“锁桶”:用每个链表的头结点作为锁对象,大大降低了锁冲突的概率。
  • 充分利用 CAS 特性。比如 size 属性通过 CAS 来更新。避免出现重量级锁的情况.
  • 优化了扩容方式:化整为零:

化整为零:

发现需要扩容的线程,只需要创建一个新的数组,同时只搬几个元素过去.
扩容期间,新老数组同时存在.
后续每个来操作 ConcurrentHashMap 的线程,都会参与搬家的过程。每个操作负责搬运一小部分元素.
搬完最后一个元素再把老数组删掉.
这个期间,插入只往新数组加.
这个期间。查找需要同时查新数组和老数组

 

ConcurrentHashMap每个哈希桶都有一把锁,只有两个线程同时访问同一个哈希桶上的数据才会出现锁竞争。

http://www.dtcms.com/a/279897.html

相关文章:

  • B站自动回复工具(破解)
  • Linux多进程
  • 国产IP摄像头存在隐蔽后门,攻击者可获取Root权限
  • 知识点2:MCP:python-sdk 核心概念
  • 丑团-h5-Mtgsig算法-分析
  • 技能升级--二分例题
  • 2025年大数据、建模与智能计算国际会议(ICBDMIC 2025)
  • 指针和数组(二)
  • AI 临床医学课题【总结】
  • Vue2 day08-10(智慧商城)
  • 应用系统报错:com.highgo.jdbc.util.PSQLException:bad value for long(APP)
  • DOM事件绑定时机:解决脚本提前加载导致的绑定失败
  • git modules
  • 8.6 Rag-基础工具介绍(开源工具)
  • 5、qt系统相关
  • 面试150 根节点到叶子节点数字之和
  • 机构参与度及其Python数据获取示例
  • SVD、DCT图像压缩实践
  • 020 实现一个简易 Shell
  • Java集合和字符串
  • JVM-1
  • 现场设备无法向视频汇聚EasyCVR视频融合平台推流的原因排查与解决过程
  • 常用的OTP语音芯片有哪些?
  • Gstreamer之”pad-added“事件
  • cron监控进程逻辑
  • C#中发布订阅的阻塞非阻塞
  • 微美全息借区块链与DRL算法打造资源管理协同架构,达成边缘计算与区块链动态适配
  • Function-——函数中文翻译渊源及历史背景
  • 学习笔记(35):了解原理:从密度到了解概率密度
  • iperf3 网络带宽测试工具学习