zoukankan      html  css  js  c++  java
  • JAVA并发体系-3-并发容器

    Copy-On-Write(COW)

    Copy-On-Write简称COW(不会产奶的奶牛),是一种用于程序设计中的优化策略。Copy On Write技术在Linux和文件系统中均有应用,Linux通过Copy On Write技术极大地减少了Fork的开销,文件系统通过Copy On Write技术一定程度上保证数据的完整性。(todo: 专门写一篇文章去阐述这个事情

    而在Java的concurrent包中也有他的身影,本节就是阐述concurrent包中的Copy On Write技术。

    Copy-On-Write的基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改,这是一种延时懒惰策略

    concurrent包中含有依据COW的组件:CopyOnWriteArrayList和CopyOnWriteArraySet

    什么是CopyOnWrite容器

    CopyOnWrite容器即写时复制的容器。从JDK1.5开始Java并发包里提供了两个使用CopyOnWrite机制实现的并发容器,它们是CopyOnWriteArrayList和CopyOnWriteArraySet。

    • 添加元素的过程:

      通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素(添加过程需要加锁),添加完元素之后,再将原容器的引用指向新的容器。

    • 优点:

      可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器。

    • 缺点:

      • 内存占用问题

        在进行写操作的时候,内存里会同时驻扎两个对象的内存,旧的对象和新写入的对象。如果这些对象占用的内存比较大,则会占用比较多的资源,造成长时间GC或频繁的GC。

        压缩容器中的元素或使用其他并发容器,如ConcurrentHashMap

      • 数据一致性问题

        只能保证数据的最终一致性,不能保证数据的实时一致性

    • 应用场景:

      读多写少的并发场景。例子比如:

      • 白名单,黑名单
      • 商品类目的访问和更新场景
    • 类库组件:CopyOnWriteArrayList和CopyOnWriteArraySet

      CopyOnWriteArrayList和CopyOnWriteArraySet分别实现了List接口和AbstractSet接口,其中CopyOnWriteArraySet含有一个CopyOnWriteArrayList实例域,进而实现COW应用。因此它们两个行为的类似

    实现原理(读/写)

    private boolean addIfAbsent(E e, Object[] snapshot) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] current = getArray();
            int len = current.length;
            ......
            Object[] newElements = Arrays.copyOf(current, len + 1);// 复制出新数组
            newElements[len] = e; // 把新元素添加到新数组里
            setArray(newElements);// 把原数组引用指向新数组
            return true;
        } finally {
            lock.unlock();
        }
    }
    ...
    final void setArray(Object[] a) {
        array = a;//直接修改引用
    }
    

    以上代码是写元素,可以发现在添加的时候是需要加锁的,否则多线程写的时候会Copy出N个副本出来。

    读元素的时候需要加锁,如果读的时候有多个线程正在向容器添加数据,还是会读到旧数据,因为写的时候不会锁住旧的容器

    ConcurrentMap

    todo: ConcurrentHashMap

    todo: ConcurrentSkipListMap ==> ConcurrentSkipListSet

    todo: 聊聊并发(四)深入分析ConcurrentHashMap

    多线程环境下,使用Hashmap进行put操作会引起死循环,导致CPU利用率接近100%,所以在并发情况下不能使用HashMap

    效率低下的HashTable容器, HashTable容器使用synchronized来保证线程安全,其他线程访问HashTable的同步方法时,可能会进入阻塞或轮询状态

    ConcurrentHashMap的锁分段技术

    ConcurrentHashMap的初始化

    定位Segment

    ConcurrentHashMap的get操作

    ConcurrentHashMap的size操作

    ConcurrentLinkedQueue

    todo: ConcurrentLinkedQueue

    todo: ConcurrentLinkedDeque

    实现一个线程安全的队列有两种实现方式:一种是使用阻塞算法,另一种是使用非阻塞算法。

    使用阻塞算法的队列可以用一个锁(入队和出队用同一把锁)或两个锁(入队和出队用不同的锁)等方式来实现,而非阻塞的实现方式则可以使用循环CAS的方式来实现,ConcurrentLinkedQueue是使用非阻塞的方式来实现线程安全队列的

    BlockingQueue

    todo: BlockingQueue

    todo: 聊聊并发(七)——Java中的阻塞队列

    阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等待队列可用。(即生产和消费

    阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程。阻塞队列就是生产者存放元素的容器,而消费者也只从容器里拿元素。

    提供了7个阻塞队列。分别是

    • ArrayBlockingQueue :一个由数组结构组成的有界阻塞队列。
    • LinkedBlockingQueue :一个由链表结构组成的有界阻塞队列。
    • PriorityBlockingQueue :一个支持优先级排序的无界阻塞队列。
    • DelayQueue:一个使用优先级队列实现的无界阻塞队列。
      • 队列使用PriorityQueue来实现。队列中的元素必须实现Delayed接口
      • 可以用于:
        • 缓存系统的设计:可以用DelayQueue保存缓存元素的有效期,使用一个线程循环查询DelayQueue,一旦能从DelayQueue中获取元素时,表示缓存有效期到了。
        • 定时任务调度。使用DelayQueue保存当天将会执行的任务和执行时间,一旦从DelayQueue中获取到任务就开始执行,从比如TimerQueue就是使用DelayQueue实现的。
    • SynchronousQueue:一个不存储元素的阻塞队列。
    • LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。
    • LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。

    阻塞队列的实现原理

    使用通知模式实现。所谓通知模式,就是当生产者往满的队列里添加元素时会阻塞住生产者,当消费者消费了一个队列中的元素后,会通知生产者当前队列可用。即使用await、signal实现

    todo: 聊聊并发(七)——Java中的阻塞队列

    参考

    1. 聊聊并发-Java中的Copy-On-Write容器
  • 相关阅读:
    网卡驱动引起openstack的mtu问题
    Ironic几种不同的场景下的网络拓扑
    enable multi-tenancy on openstack pike
    galera断电后无法重建集群
    Fabric单节点安装备忘
    OpenStack Ironic 常见问题
    Enable multi-tenancy on ironic
    kolla-ansible快速入门
    kolla管理openstack容器
    d2.js学习笔记(七)——动态SVG坐标空间
  • 原文地址:https://www.cnblogs.com/cheaptalk/p/12549668.html
Copyright © 2011-2022 走看看