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

CopyOnWriteArrayList

作者头像
崔笑颜
发布2020-06-08 16:56:26
4290
发布2020-06-08 16:56:26
举报
文章被收录于专栏:小小码农一个。

CopyOnWriteArrayList是怎么实现写有锁,读无锁,读写之间不堵塞的?(加强版读写分离源码剖析)

CopyOnWriteArrayList是ArrayList的线程安全版本,从名字推测,CopyOnWriteArrayList是在有写操作的时候会copy一份数据,然后写完再设置成新的数据。CopyOnWriteArrayList适用于读多写少的并发场景。而CopyOnWriteArraySet也是线程安全的Set版本,也是CopyOnWriteArrayList来代理读写分离的,而且还保留了Set的特性(无序、无下标)。那么我就去介绍他们的其中一个CopyOnWriteArrayList!

CopyOnWriteArrayList思想

我们考虑这么一个问题,比如我在写一篇博客或者是修改一篇博客,其实我正在修改只是没有点击保存重新发布而已,所以你们看到的就是我没有修改之前的那一篇(旧数组)。只要这时我写完了修改完了,点击保存(替换地址),而这时你们看的就是我新修改完后的博客(替换地址后的新数组)了!

因为无计其数的读者正在读同一篇博客,他们之间肯定是不可以阻塞的!假如阻塞的话,就面临排队读博客了(举个例子,不是现实)!而且我们还得保证博主在修改博客的时候,读者还能读到博客内容,这时候就需要读写分离了(读与写同时并发,互不影响)!即原生操作实现写有锁,读无锁,读写之间不堵塞的效果!

CopyOnWriteArrayList简单介绍

  • 线程安全的ArrayList,加强版读写分离
  • 写有锁,读无锁,读写之间不堵塞,优于读写锁
  • 写入时,先copy一个容器副本、再添加新元素,最后替代引用
  • 使用方式与ArrayList无异

CopyOnWriteArrayList使用

代码语言:javascript
复制
	//与普通ArrayList使用方式无异
	List<String> list = new CopyOnWriteArrayList<String>();
	list.add("Ziph");

CopyOnWriteArrayList源码剖析

我们知道,CopyOnWriteArrayList是读写操作分离的,我们肯定还得去拿add方法说事!看源码~

代码语言:javascript
复制
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();
    }
}

首先,add方法是添加为集合添加元素的方法,他在方法内加了一把锁(lock),来保障线程是安全的。那么进入源码的操作内!接下来是这一部分:

代码语言:javascript
复制
/** The array, accessed only via getArray/setArray. */
private transient volatile Object[] array;

Object[] elements = getArray();

一个Object类型的数组element(意为元素)获得了一个数组,即:getArray();点击去是这样的~

代码语言:javascript
复制
final Object[] getArray() {
    return array;
}
final void setArray(Object[] a) {
    array = a;
}

而且我们看还有一个setArray方法!

代码语言:javascript
复制
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);

其实这些操作分析起来很简单,就是拿到了一个Object类型数组(可以存放任何类型),得到数组的长度,copy一个数组长度比它大1的新数组。其次将传入的参数e插入到了新数组的扩容后的最后一个位置上,最后setArray把新地址替换原地址,实现写操作!

代码语言:javascript
复制
return true;
lock.unlock();
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-03-17,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • CopyOnWriteArrayList思想
  • CopyOnWriteArrayList简单介绍
  • CopyOnWriteArrayList使用
  • CopyOnWriteArrayList源码剖析
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档