JavaEE——线程安全的集合类

JavaEE传送门

JavaEE

JavaEE——CAS

JavaEE——JUC


目录

  • 线程安全的集合类
    • 1. 多线程环境使用 ArrayList
    • 2. 多线程环境使用队列
    • 3. 多线程环境使用哈希表
    • 4. 分段锁


线程安全的集合类

标准库里大部分的集合类, 都是线程不安全的.

少数几个安全的: Vector, Stack, HashTable (不太推荐使用)

1. 多线程环境使用 ArrayList

  • 自己使用同步机制 (synchronized 或者 ReentrantLock)

  • 如果需要在多线程环境下保证集合类的线程安全, 最简单的做法, 就是自己加锁Collections.synchronizedList(new ArrayList); 就是在外面套上一层壳, 壳上加锁了.

  • 使用 CopyOnWriteArrayList (不加锁保证线程安全)

    CopyOnWrite, 写(修改)时拷贝(复制)

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

    # 注意 #

    这个操作适用范围非常有限, 如果元素特别多, 修改的特别频繁, 就不太适合使用这种方式了.


2. 多线程环境使用队列

  1. ArrayBlockingQueue (基于数组实现的阻塞队列)

  2. LinkedBlockingQueue (基于链表实现的阻塞队列)

  3. PriorityBlockingQueue (基于堆实现的带优先级的阻塞队列)

  4. TransferQueue (最多只包含一个元素的阻塞队列)


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

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

  1. HashTable (不推荐)
  2. ConcurrentHashMap (推荐)

HashTable

  • Hashtable 属于无脑给各种方法加 synchronized , 相当于给 this 加锁.

    相当于是针对哈希表对象来加锁, 一个哈希表, 只有一个锁.

    如果有多个线程, 无论都是如何操作这个哈希表, 都会产生锁冲突.

    # 注意 # 产生锁冲突, 对性能影响是非常大的.

    JavaEE——线程安全的集合类_第1张图片

  • HashTable 扩容:

    当 put 元素的时候, 发现当前的负载因子已经超过阙值, 就需要触发扩容, 申请一个更大的数组, 然后把之前的旧数据给搬到新的数组上.

    # 注意 # 但这里有一个很大的问题:

    如果元素个数特别多, 搬运操作的开销就会很大. 执行一个 put 操作, 正常瞬间完成 O(1). 但是触发扩容的这一下 put, 就可能会卡很久.

ConcurrentHashMap

  • 加锁的方式仍然是是用 synchronized, 但是不是锁整个对象, 而是 “锁桶”(哈希桶) (用每个链表的头结点作为锁对象), 大大降低了锁冲突的概率.
    JavaEE——线程安全的集合类_第2张图片

  • 读操作没有加锁(但是使用了 volatile 保证从内存读取结果), 只对写操作进行加锁.

  • 充分利用 CAS 特性. 比如像维护元素个数, 都是通过 CAS 来更新. 避免出现重量级锁的情况.

  • 对于扩容操作, 进行了特殊的优化: “化整为零”

    ConcurrentHashMap 在扩容的时候, 就不再是一次性完成搬运了,

    • 在扩容过程中, 旧的和新的会同时存在一段时间, 每次进行哈希表的操作, 都会把旧的内存上的元素搬运一部分到新的空间上
    • 在这个过程中, 如果要查询元素, 旧的和新的一起查
    • 如果要插入元素, 直接往新的上插入
    • 如果是删除元素, 直接删了不用搬运了

小知识:

  • HashMap key 允许为 null
  • HashTable 和 ConurrentHashMap key 不能为 null

4. 分段锁

旧版本的 ConcurrentHashMap 的实现方式

注 : 从 Java 8 开始, 就没有了.

好几个链表公用同一把锁, (锁冲突概率要比每个链表一把锁更高, 代码实现起来更复杂了)


(( ◞•̀д•́)◞⚔◟(•̀д•́◟ ))

以上就是今天要讲的内容了,希望对大家有所帮助,如果有问题欢迎评论指出,会积极改正!!
JavaEE——线程安全的集合类_第3张图片
JavaEE——线程安全的集合类_第4张图片

这里是Gujiu吖!!感谢你看到这里
祝今天的你也
开心满怀,笑容常在。

你可能感兴趣的:(JavaEE,java-ee,安全)