`

CopyOnWrite实现原理

阅读更多

Java中提供了两个CopyOnWrite容器,分别是CopyOnWriteArrayList和CopyOnWriteArraySet。如果想要高效的使用这两个容器,我觉的首先要弄懂CopyOnWrite的原理。那么下面就先来谈谈什么是CopyOnWrite吧。

什么是CopyOnWrite

CopyOnWrite即写时复制,该机制在于控制对数据的操作,什么时候需要对数据的操作进行控制呢,当然是在并发的时候,如果程序只是单线程的,所有对数据的操作都是顺序执行,那么数据的一致性就自然能得到保证。但是当有多个线程并发对数据进行操作的时候,情况就没那么简单了,一个线程修改了数据,另一个线程在数据被修改的过程中又读取了数据并对它进行修改,然后把修改的结果写回主内存,于是就会丢失一个线程对数据所做的修改。这种情况可以通过线程同步来解决,但是同步代码会大大降低并发效率。那么,有没有什么更好的方法来解决这个问题呢,当然,这个方法就是CopyOnWrite!首先我们可以来分析一下对数据的并发访问有哪些情况,如果我们仔细一想就会发现,并发访问数据的情况也无非下面这几种:读读、读写、写读、写写。针对这几种情况,可以分别对并发效率进行优化。

  • 读读这种情况是不需要加锁的,多个线程可以同时读取数据。
  • 读写这种情况便要考虑到对数据一致性的要求高低,我们可以将读锁写锁分离,读取数据时不加锁,修改数据时加写锁,这样相当于只同步了执行写操作的线程,但是由于写线程在修改数据时,读线程仍然可以读取数据,所以这样会造成一定程度的数据不一致。如果对数据一致性要求比较高,可以在修改数据时同时加写锁和读锁,这样写线程在修改数据时,读线程也必须等待。
  • 写读这种情况,同样可以使用读写锁分离的方式,但是更好的方法就是使用CopyOnWrite,对读线程不加锁,写线程修改数据时,先把原数据复制一份进行修改,读线程仍然读到的是旧数据,修改完之后再将原数据的引用指向新的数据,注意这时候写线程仍然是需要加锁的,否则多个线程将会复制出多个副本。
  • 写写这种情况就只好进行同步了,但是仍然可以通过降低锁的粒度来进行优化。

其实上面所讲到的这些,不仅仅是在Java多线程并发处理领域有应用,在数据库并发事务处理方面也有广泛应用,这篇文章数据库事务与其隔离级别中有相关概念的介绍。

CopyOnWrite适用场景

CopyOnWrite机制适用于读多写少的场景,比如搜索引擎对某些关键词的过滤使用的黑名单,黑名单很久才会更新一次,但是几乎每时每刻都在被读取。这种机制不适用于对数据实时性要求较高的场景中,因为一个线程修改了数据,其他线程并不一定能够马上读取到新的数据。

分享到:
评论

相关推荐

    Java并发CopyOnWrite容器原理解析

    CopyOnWriteArrayList的实现原理是使用ReentrantLock锁来确保线程安全,在添加元素时,首先锁定当前容器,然后复制出一个新的数组,添加元素到新数组中,最后将原数组引用指向新数组。读取操作不需要加锁,可以直接...

    聊聊并发系列文章

    1. 聊聊并发(一)深入分析Volatile的实现原理 2. 聊聊并发(二)Java SE1.6中的Synchronized 3. 聊聊并发(三)Java线程池的分析和使用 4. 聊聊并发(四)深入分析ConcurrentHashMap 5. 聊聊并发(五)原子操作的...

    java高并发锁的3种实现示例代码

    其实现原理是,每次读取数据时,不加锁,只有当写操作时,才加锁,以避免读写冲突。以下是乐观锁的实现代码: ```java public Object get(Object key) { Object val = null; if((val = map.get(key) == null) { ...

    多线程并发集合资料.zip

    3. **CopyOnWrite集合使用和原理**: CopyOnWrite集合在并发环境下,通过在修改时创建底层数组副本来实现线程安全。这使得读操作无需加锁,提高了并发性能。但因为频繁复制会导致空间开销大,所以适用于写入操作不...

    阿里资深技术专家:在各阶段中3年经验的java程序员应该具备哪些技术能力

    阿里资深技术专家建议java程序员应该具备ArrayList、LinkedList、Hashtable、HashMap、ConcurrentHashMap、HashSet等实现类的底层实现原理的知识,并且了解CopyOnWrite容器和Queue的实现原理。 特别是...

    JAVA并发容器代码随读1

    不同的并发容器根据其设计目的和应用场景,采用不同的实现方式,如 BlockingQueue 的阻塞等待、DelayQueue 的延迟处理、ConcurrentMap 的分段锁、以及 CopyOnWrite 系列的写时复制。理解和掌握这些并发容器的原理和...

    Java服务器端开发面试.doc

    Java服务器端开发面试题 Java服务器端开发面试题篇1 Hashcode()和equals(), 明白背后的原理,包括hashcode()的用法,各自的区别,如何,何时覆盖,为何覆盖 区别new String()和 申明的字符串的区别,String不变量,堆...

    Tomcat均衡负载,集群配置

    在Tomcat的`conf/context.xml`文件中,添加`<Manager>`元素,并设置`copyOnWrite`和`shared`属性为`true`。 2. **生成独一无二的JVMRoute**:每个Tomcat实例需要一个唯一的ID,这可以通过在`server.xml`中的`Engine...

    对java的BitSet的多线程并发的探索

    5. **CopyOnWrite机制**:在某些场景下,如果写操作远少于读操作,可以使用CopyOnWriteArrayList或CopyOnWriteArraySet的思想,复制一个新的BitSet并在新的副本上进行修改,然后在合适的时候替换原BitSet。...

    Java从同步容器到并发容器的操作过程

    除了`CopyOnWrite`系列容器,`java.util.concurrent`包还包含其他并发容器,如`ConcurrentHashMap`,它使用分段锁技术,允许并发读写,相比于`HashTable`有更高的并发性能。`ConcurrentLinkedQueue`是一个无界的线程...

Global site tag (gtag.js) - Google Analytics