CopyOnWriteArrayList详解

时间:2020-06-30 22:36:32   收藏:0   阅读:62

CopyOnWriteArrayList详解

简介

Copy-On-Write(COW):
开始时共享同一资源,但一个线程修改部分内容时,才会用修改后的内容覆盖旧的内容.是一种延时懒惰策略.

有两种COW机制的并发容器:


原理


实现

添加元素

public boolean add(E e) {
    final ReentrantLock lock = this.lock;
    lock.lock(); 加锁
    try {
        Object[] elements = getArray();
        int len = elements.length;
        Object[] newElements = Arrays.copyOf(elements, len + 1); // 复制原容器中的元素
        newElements[len] = e; // 添加新增的元素
        setArray(newElements); // 将引用指向新容器
        return true;
    } finally {
        lock.unlock(); // 释放锁
    }
}

步骤:

  1. 加锁
  2. 复制原来的元素到新容器中
  3. 向新容器中添加元素
  4. 更新引用指向新容器

获取元素

public E get(int index) {
    return get(getArray(), index);
}

注: 获取元素无需加锁.

更新元素

public E set(int index, E element) {
    final ReentrantLock lock = this.lock;
    lock.lock(); // 加锁
    try {
        Object[] elements = getArray(); // 获取旧容器
        E oldValue = get(elements, index);

        if (oldValue != element) { // 若指定位置的元素与设定的新值不同,则构造新容器并更新该元素
            int len = elements.length;
            Object[] newElements = Arrays.copyOf(elements, len);
            newElements[index] = element;
            setArray(newElements);
        } else { // 若指定位置的元素与设定的元素相同,则无需更新
            setArray(elements);
        }
        return oldValue;
    } finally {
        lock.unlock(); // 释放锁
    }
}

步骤:

  1. 获取旧的容器.
  2. 若指定位置的元素与设定的新值不同,则构造新容器,并更新该位置上的值.
  3. 若设定的新值与旧值相同,则无需更新.

删除元素

类似与添加元素.

  1. 加锁
  2. 构造新容器
  3. 更新引用指向新容器
  4. 释放锁

添加不存在的元素

private boolean addIfAbsent(E e, Object[] snapshot) {
    final ReentrantLock lock = this.lock;
    lock.lock(); // 加锁
    try {
        Object[] current = getArray();
        int len = current.length;
        if (snapshot != current) {
            int common = Math.min(snapshot.length, len);
            for (int i = 0; i < common; i++)
                if (current[i] != snapshot[i] && eq(e, current[i]))
                    return false;
            if (indexOf(e, current, common, len) >= 0)
                    return false;
        }
        Object[] newElements = Arrays.copyOf(current, len + 1); // 复制旧容器中的元素
        newElements[len] = e; // 向新容器中新增元素
        setArray(newElements); // 更新引用
        return true;
    } finally {
        lock.unlock(); // 解锁
    }
}

流程:

  1. 加锁
  2. 检查新增的元素是否已存在,若已存在,则无需新增
  3. 若不存在,则构造新容器,将旧值复制到新容器中,并添加新值
  4. 释放锁

应用

参考:

原文:https://www.cnblogs.com/truestoriesavici01/p/13216170.html

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!