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

【多线程】线程安全的集合类

文章目录

    • 1. 多线程环境使用ArrayList
      • 1.1 自己使用同步机制
      • 1.2 Collections.synchronizedList(new ArrayList);
      • 1.3 使用 CopyOnWriteArrayList
    • 2. 多线程使用队列
    • 3. 多线程环境使用哈希表
      • 3.1 HashTable
      • 3.2 ConcurrentHashMap
      • 3.3 Hashtable和HashMap、ConcurrentHashMap 之间的区别?

学到现在,我们会发现原先学的大多集合类在多线程环境中使用并不是安全的,在并发编程中使用起来会有诸多问题,那么下面我们就要学习新的集合类和并发集合。
PS:Vector, Stack, HashTable, 是线程安全的,但不建议用,这是Java中旧的集合类,它们在性能、可读性、维护性等方面已经不如现在新的集合类和并发集合。

1. 多线程环境使用ArrayList

1.1 自己使用同步机制

自己使用同步机制,就是为ArrayList加锁,我们可以使用synchronized或ReentrantLock。

1.2 Collections.synchronizedList(new ArrayList);

synchronizedList 是标准库提供的一个基于 synchronized 进行线程同步的 List.
synchronizedList 的关键操作上都带有 synchronized,实现线程安全。

1.3 使用 CopyOnWriteArrayList

CopyOnWrite容器即写时复制的容器。
当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。
这样做的好处是我们可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。
所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器。
优点
在读多写少的场景下, 性能很高, 不需要加锁竞争。
缺点

  1. 占用内存较多。
  2. 新写的数据不能被第一时间读取到。

2. 多线程使用队列

  1. ArrayBlockingQueue
    基于数组实现的阻塞队列
  2. LinkedBlockingQueue
    基于链表实现的阻塞队列
  3. PriorityBlockingQueue
    基于堆实现的带优先级的阻塞队列
  4. TransferQueue
    最多只包含一个元素的阻塞队列

3. 多线程环境使用哈希表

HashMap本身不是线程安全的。
并发编程中可以使用HashTable和ConcurrentHashMap。

3.1 HashTable

HashTable实现线程安全就是把关键的方法都加上锁,例如get(),put()方法,这个时候当多个线程访问HashTable就会发生锁冲突。
其实就相当于给HashTable对象进行了加锁,这个时候也会造成许多的弊端,例如:

  1. size属性也被加锁,那么多线程同时访问size的速度就会变慢,降低了效率。
  2. 当发生扩容操作时,就由该线程完成整个扩容过程. 这个过程会涉及到大量的元素拷贝, 效率会非常低。

3.2 ConcurrentHashMap

相比HashTable,ConcurrentHashMap就进行了优化,只对写操作进行加锁(锁的不是整个对象,而是‘桶锁’,以每个链表的头节点作为锁,那么,只有多线程同时访问一个桶时才会锁冲突),读并没有加锁(但是使用了volatile,保证内存的可见性)那么多线程读时,效率就会大大提升。
充分利用 CAS 特性:
比如 size 属性通过 CAS 来更新. 避免出现重量级锁的情况。
优化了扩容方式:
化整为零:
发现需要扩容的线程, 只需要创建一个新的数组, 同时只搬几个元素过去,
扩容期间, 新老数组同时存在,后续每个来操作 ConcurrentHashMap 的线程, 都会参与搬家的过程. 每个操作负责搬运一小部分元素, 搬完最后一个元素再把老数组删掉。这个期间, 插入只往新数组加,这个期间, 查找需要同时查新数组和老数组。

3.3 Hashtable和HashMap、ConcurrentHashMap 之间的区别?

HashMap: 线程不安全. key 允许为 null
Hashtable: 线程安全. 使用 synchronized 锁 Hashtable 对象, 效率较低. key 不允许为 null.
ConcurrentHashMap: 线程安全. 使用 synchronized 锁每个链表头结点, 锁冲突概率低, 充分利用CAS 机制. 优化了扩容方式. key 不允许为 null

http://www.lryc.cn/news/178622.html

相关文章:

  • Goby 漏洞发布|Revive Adserver 广告管理系统 adxmlrpc.php 文件远程代码执行漏洞(CVE-2019-5434)
  • Docker(三)、Dockerfile探究
  • C++读取文件夹下多个文件,包括图片等等
  • DirectX 12 学习笔记 -结构
  • 【Redis】Redis 的学习教程(十二)之在 Redis使用 lua 脚本
  • 标准/扩展库中对象的导入与使用
  • 87、Redis 的 value 所支持的数据类型(String、List、Set、Zset、Hash)---->List相关命令
  • Celery结合flask完成异步任务与定时任务
  • 前端项目练习(练习-001-纯原生)
  • 基于微信小程序的游戏账号交易买卖平台设计与实现(源码+lw+部署文档+讲解等)
  • 2023 年 Bitget Wallet 测评
  • 医疗图像分割指标
  • 零代码编程:用ChatGPT批量修改文件夹名称中的大小写
  • webpack:详解cache模块常用配置
  • 云原生Kubernetes:Pod控制器
  • 数据库基础与MySQL入门
  • 探索Java爬虫框架:解锁网络数据之门
  • 智慧燃气平台的总体架构到底应怎样设计?
  • MonkeyRunner测试步骤
  • Konva基本处理流程和相关架构设计
  • 人工智能AI知多少?
  • leetcode1610. 可见点的最大数目(java)
  • Apache Flume
  • 【切片】基础不扎实引发的问题
  • CVE-2023-5129 libwebp堆缓冲区溢出漏洞影响分析
  • leetcode做题笔记155. 最小栈
  • 蓝海彤翔亮相2023新疆网络文化节重点项目“新疆动漫节”
  • 【AI视野·今日NLP 自然语言处理论文速览 第四十四期】Fri, 29 Sep 2023
  • 【VsCode】vscode创建文件夹有小图标显示和配置
  • celery分布式异步任务队列-4.4.7