IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> java并发包之CopyOnWriteArrayList源码分析 -> 正文阅读

[Java知识库]java并发包之CopyOnWriteArrayList源码分析

大多数情况下读操作是远远大于写操作的,读操作本身不会修改集合中的数据,所以说读操作和写操作一样加锁的话对资源是一种极大的浪费。而java.util.concurrent包刚好为我们提供了一种读不加锁写加锁的集合,而且读写不互斥,只有写写之间才会阻塞,让我们在构建多线程的应用时,既保证了运行效率,又保证了数据的一致性,废话不多说,我们直接开撸源码。

首先是属性,CopyOnWriteArrayList重要的属性比较少:

    /** 保护所有并发资源的可重入锁 */
    final transient ReentrantLock lock = new ReentrantLock();

    /** 集合底层的对象数组,只能通过getArray/setArray访问*/
    /** 使用volatile保证了线程间的可见性*/
    private transient volatile Object[] array;
    
    /** 调用native方法的UNSAFE类 */
    private static final sun.misc.Unsafe UNSAFE;
    
    /** 集合的锁属性相对于集合对象在内存中起始地址的偏移量 */
    private static final long lockOffset;

读数据的get(int index)函数

    /**
     * {@inheritDoc}
     *
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E get(int index) {
        return get(getArray(), index);
    }

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

可以看到实现非常简单,直接返回数组中参数下标对应的元素。

重点在于写操作,下面来看add(E e)函数


    /**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return {@code true} (as specified by {@link Collection#add})
     */
    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();
        }
    }

CopyOnWriteArrayList?类的所有可变操作(add,set等等)都是通过创建底层数组的新副本来实现的。当 List 需要被修改的时候,并不直接修改原有数组对象,而是对原有数据进行一次拷贝,将修改的内容写入副本中。写完之后,再将修改完的副本替换成原来的数据,这样就可以保证写操作不会影响读操作了。

从?CopyOnWriteArrayList?的名字可以看出,CopyOnWriteArrayList?是满足?CopyOnWrite?的 ArrayList,所谓?CopyOnWrite?的意思:、就是对一块内存进行修改时,不直接在原有内存块中进行写操作,而是将内存拷贝一份,在新的内存中进行写操作,写完之后,再将原来指向的内存指针指到新的内存,原来的内存就可以被回收。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-22 20:22:50  更:2022-03-22 20:27:37 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 6:17:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码