zoukankan      html  css  js  c++  java
  • CopyOnWrite解析

    核心思想

    读写分离,空间换时间,避免为保证并发安全导致的激烈的锁竞争。

    关键点

    1、CopyOnWrite适用于读多写少的情况,最大程度的提高读的效率;
    2、CopyOnWrite是最终一致性,在写的过程中,原有的读的数据是不会发生更新的,只有新的读才能读到最新数据;
    3、如何使其他线程能够及时读到新的数据,需要使用volatile变量;
    4、写的时候不能并发写,需要对写操作进行加锁;

    源码解析

    CopyOnWriteArrayList 相对于 ArrayList 线程安全,底层通过复制数组的方式来实现,其核心概念就是: 数据读取时直接读取,不需要锁,数据写入时,需要锁,且对副本进行操作。那么当数据的操作以读取为主时,我们便可以省去大量的读锁带来的消耗。同时为了能让多线程操作List时,一个线程的修改能被另一个线程立马发现,CopyOnWriteList采用了Volatile关键词来进行修饰,即每次数据读取不从缓存里面读取,而是直接从数据的内存地址中读取。
    以CopyOnWriteArrayList 的add()操作为例来看

      // 这个数组是核心的,因为用volatile修饰了
      // 只要把最新的数组对他赋值,其他线程立马可以看到最新的数组
      private transient volatile Object[] array;
    
      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;
    
              // 然后把副本数组赋值给volatile修饰的变量
              setArray(newElements);
              return true;
    
    
          } finally {
              lock.unlock();
          }
      }
    

    结论

    总结而言,多线程实现COW实际上就是以空间换取时间使得数据读取时不需要锁。只是减少了读锁的开销,但与常规的多线程操作共享数据的本质没有什么区别。

    参考

    https://zhuanlan.zhihu.com/p/114547256
    https://cloud.tencent.com/developer/article/1821632
    https://blog.csdn.net/javageektech/article/details/108114252

  • 相关阅读:
    数据库主键生成策略
    弹出窗返回数据实体对象或对象集
    我的家乡话,模糊和清晰的记忆......
    曾经年少
    获取父页面URL的参数对应值及左对齐字符串
    .Net编程规范
    DBdifference
    GridView翻页时保持CheckBox选择状态
    .CS中的javascript
    (转)程序员职业规划
  • 原文地址:https://www.cnblogs.com/huangjianping/p/15060895.html
Copyright © 2011-2022 走看看