前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CopyOnWriteArrayList 源码分析

CopyOnWriteArrayList 源码分析

作者头像
itliusir
发布2020-01-06 11:28:23
2900
发布2020-01-06 11:28:23
举报
文章被收录于专栏:刘君君刘君君刘君君

摘要:

  1. CopyOnWriteArrayList 是怎么保证线程安全的
  2. 适用的场景

TOP 带着问题看源码

  1. CopyOnWriteArrayList 是怎么保证线程安全的
  2. 适用的场景

1. 基本介绍

顾名思义,这是一个每次写入都采用先复制再写入的方式来实现的线程安全的 List。这样的好处是可以读写并行,而且实现简单。

2. 成员变量分析

// lock 锁
final transient ReentrantLock lock = new ReentrantLock();
// 存放数据的数组
private transient volatile Object[] array;

// getter
final Object[] getArray() {
    return array;
}
// setter
final void setArray(Object[] a) {
    array = a;
}

3. 核心方法分析

3.1 add(E e)

核心逻辑就是使用数组copy把旧的数据复制到新的数组(比旧的数组长度大1),然后把存放数据的数组指向新的数组。加锁是解决线程不安全问题,可以明白问题 TOP 1 的线程安全问题是由 COW+Lock 来保证的。

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();
    }
}

3.2 get(int index)

获取指定 index 的数据比较简单,可以看到查询是无锁的

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

private E get(Object[] a, int index) {
    return (E) a[index];
}

4. 总结

经过前面的分析,可以发现其更新操作都是贯彻 COW 思想,那就有可能写入还在复制副本期间读的是旧的数据,回到问题 TOP 2 那对应的场景也可以猜到:

适用于写少读多且能容忍读写的短暂不一致

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-01-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • TOP 带着问题看源码
  • 1. 基本介绍
  • 2. 成员变量分析
  • 3. 核心方法分析
    • 3.1 add(E e)
      • 3.2 get(int index)
      • 4. 总结
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档