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


    学到现在,我们会发现原先学的大多集合类在多线程环境中使用并不是安全的,在并发编程中使用起来会有诸多问题,那么下面我们就要学习新的集合类和并发集合。
    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

  • 相关阅读:
    Java摆烂基础学习三~程序流程控制
    股票交易接口的分类webService接口
    【OpenCV入门】第九部分——模板匹配
    Docker离线安装-liunx系统
    4.10、matlab生成脉冲序列:pulstran()函数
    python随手小练1
    小侃设计模式(十三)-策略模式
    Java代理
    java计算机毕业设计springboot+vue学生宿舍管理系统 elementui
    [软件工具][原创]pcl引用库一键配置到VisualStudio中支持vs2015-v2022使用教程
  • 原文地址:https://blog.csdn.net/weixin_73392477/article/details/133417704