多线程环境下如何安全的使用线性表, 队列, 哈希表

本文介绍了如何在多线程环境中安全地使用ArrayList、队列(如ArrayBlockingQueue、LinkedBlockingQueue等)和HashMap,包括CopyOnWriteArrayList的使用以及ConcurrentHashMap与HashTable的线程安全特性比较。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今日鸡汤

内心丰盈者, 独行也如众

安全使用ArrayList

  1. 使用synchronized锁或者reentrantLock锁
  2. 使用CopyOnWriteArrayList(COW写时拷贝)类来代替ArrayList类.
  1. 多个线程对CopyOnWriteArrayList里面的ArrayList进行读操作, 不会发生线程安全问题, 不做任何处理
  2. 多个线程对CopyOnWriteArrayList里面的ArrayList进行写操作, 会为每个线程创建一个副本, 各个线程在各自独立的副本上进行修改, 最后不会进行汇总, 最后一个完成写操作的副本将会代替旧的ArrayList(牺牲了实时性来确保线程安全). 如果在写操作期间有线程对其进行读操作, 会读旧的(修改之前的)ArrayList. 本质上是引用之间的赋值. 这种方法适用于读频繁, 不经常写入的情况. 如服务器的配置文件.
  3. CopyOnWriteArrayList的局限性在于:
    (1) 牺牲了实时性, 同时多个线程进行写操作时之会将最后一个完成写操作的副本代替原来的ArrayList, 而率先完成写操作的副本将会作废, 也因此这种方法只适用于读频繁而不经常写的情况
    (2) 这种方法也只适用于ArrayList较小的情况, 否则在创建副本时将会付出巨大的开销.
    (3) 服务器的配置文件就是采用这种写时拷贝的方式来对配置文件进行修改的, 这个功能叫热加载

安全使用队列

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

安全使用HashMap

  1. 使用HasHTable代替HashMap, HashTable中的关键方法进行了上锁, 使用时是线程安全的
  2. 使用ConcurrentHashMap代替HashMap

ConcurrentHashMap和HashTable的区别:

  1. ConcurrentHashMap的锁粒度更小, 锁冲突发生的概率小.
    HashTable的锁对象是整个哈希表, 这就意味着对哈希表中的任何元素进行操作都会上锁, 但是有些操作是不需要上锁的.
    在这里插入图片描述而ConcurrentHashMap的锁对象是单个链表, 这就大大细化了锁的粒度, 大大减小了发生锁冲突的概率, 且提高了性能
    在这里插入图片描述
  2. ConcurrentHashMap对读操作不上锁, 只对写操作上锁. 通过volatile关键字+原子操作写来确保边读边写的线程安全, 避免脏读的发生.
  3. ConcurrentHashMap使用了CAS操作, 尽量减少上锁的操作. 提高并发性能.
  4. 扩容方面, ConcurrentHampMap使用了化整为零的方式.
    (1) HashTable在进行扩容时, 容量扩为原来的两倍, 将原哈希表中的数据复制到新表中, 因为其是对整个哈希表上锁, 所以在整个哈希表未完成扩容时, 对其的读写操作都会陷入阻塞, 这大大降低了性能. 由于扩容是在put时发生的, 所以会造成某次put操作非常慢.
    (2) ConcurrentHashMap在扩容时, 由于锁对象是链表, 所以在进行数据迁移时, 各个链表可以独立迁移, 这样在一次迁移中只对正在迁移的链表上锁, 针对其他链表的读写操作还可以执行. 每一次put操作只迁移一部分数据, 这会造成在一段时间内就哈希表和新哈希表共存的情况, 迁移时将链表节点从旧表删除, 在新表中插入
    如果要执行put操作, 则直接在新的哈希表中添加
    如果要执行take操作, 则对原哈希表和新哈希表都进行检索
    直到新哈希表扩容完成(数据全部迁移), 再释放旧的哈希表.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

With Order @!147

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值