Java中提供了两个CopyOnWrite容器,分别是CopyOnWriteArrayList和CopyOnWriteArraySet。如果想要高效的使用这两个容器,我觉的首先要弄懂CopyOnWrite的原理。那么下面就先来谈谈什么是CopyOnWrite吧。
什么是CopyOnWrite
CopyOnWrite即写时复制,该机制在于控制对数据的操作,什么时候需要对数据的操作进行控制呢,当然是在并发的时候,如果程序只是单线程的,所有对数据的操作都是顺序执行,那么数据的一致性就自然能得到保证。但是当有多个线程并发对数据进行操作的时候,情况就没那么简单了,一个线程修改了数据,另一个线程在数据被修改的过程中又读取了数据并对它进行修改,然后把修改的结果写回主内存,于是就会丢失一个线程对数据所做的修改。这种情况可以通过线程同步来解决,但是同步代码会大大降低并发效率。那么,有没有什么更好的方法来解决这个问题呢,当然,这个方法就是CopyOnWrite!首先我们可以来分析一下对数据的并发访问有哪些情况,如果我们仔细一想就会发现,并发访问数据的情况也无非下面这几种:读读、读写、写读、写写。针对这几种情况,可以分别对并发效率进行优化。
- 读读这种情况是不需要加锁的,多个线程可以同时读取数据。
- 读写这种情况便要考虑到对数据一致性的要求高低,我们可以将读锁和写锁分离,读取数据时不加锁,修改数据时加写锁,这样相当于只同步了执行写操作的线程,但是由于写线程在修改数据时,读线程仍然可以读取数据,所以这样会造成一定程度的数据不一致。如果对数据一致性要求比较高,可以在修改数据时同时加写锁和读锁,这样写线程在修改数据时,读线程也必须等待。
- 写读这种情况,同样可以使用读写锁分离的方式,但是更好的方法就是使用CopyOnWrite,对读线程不加锁,写线程修改数据时,先把原数据复制一份进行修改,读线程仍然读到的是旧数据,修改完之后再将原数据的引用指向新的数据,注意这时候写线程仍然是需要加锁的,否则多个线程将会复制出多个副本。
- 写写这种情况就只好进行同步了,但是仍然可以通过降低锁的粒度来进行优化。
其实上面所讲到的这些,不仅仅是在Java多线程并发处理领域有应用,在数据库并发事务处理方面也有广泛应用,这篇文章数据库事务与其隔离级别中有相关概念的介绍。
CopyOnWrite适用场景
CopyOnWrite机制适用于读多写少的场景,比如搜索引擎对某些关键词的过滤使用的黑名单,黑名单很久才会更新一次,但是几乎每时每刻都在被读取。这种机制不适用于对数据实时性要求较高的场景中,因为一个线程修改了数据,其他线程并不一定能够马上读取到新的数据。
相关推荐
CopyOnWriteArrayList的实现原理是使用ReentrantLock锁来确保线程安全,在添加元素时,首先锁定当前容器,然后复制出一个新的数组,添加元素到新数组中,最后将原数组引用指向新数组。读取操作不需要加锁,可以直接...
其实现原理是,每次读取数据时,不加锁,只有当写操作时,才加锁,以避免读写冲突。以下是乐观锁的实现代码: ```java public Object get(Object key) { Object val = null; if((val = map.get(key) == null) { ...
3. **CopyOnWrite集合使用和原理**: CopyOnWrite集合在并发环境下,通过在修改时创建底层数组副本来实现线程安全。这使得读操作无需加锁,提高了并发性能。但因为频繁复制会导致空间开销大,所以适用于写入操作不...
阿里资深技术专家建议java程序员应该具备ArrayList、LinkedList、Hashtable、HashMap、ConcurrentHashMap、HashSet等实现类的底层实现原理的知识,并且了解CopyOnWrite容器和Queue的实现原理。 特别是...
不同的并发容器根据其设计目的和应用场景,采用不同的实现方式,如 BlockingQueue 的阻塞等待、DelayQueue 的延迟处理、ConcurrentMap 的分段锁、以及 CopyOnWrite 系列的写时复制。理解和掌握这些并发容器的原理和...
- 面试时经常会考察对List、Map、Set接口以及其实现类的理解,如ArrayList、LinkedList、Hashtable、HashMap、ConcurrentHashMap和HashSet的底层实现原理和优缺点。熟悉CopyOnWrite容器和Queue也是加分项,它们在...
本PDF文档涉及了Java多线程的全面介绍,分为基础篇、原理篇和JDK工具篇三个部分,旨在帮助读者深入了解Java多线程的概念、原理及实践应用。 #### 基础篇 **1. 进程与线程基本概念** - **进程**:是程序的一次执行...
除了`CopyOnWrite`系列容器,`java.util.concurrent`包还包含其他并发容器,如`ConcurrentHashMap`,它使用分段锁技术,允许并发读写,相比于`HashTable`有更高的并发性能。`ConcurrentLinkedQueue`是一个无界的线程...
- **RocketMQ**:基于Kafka原理改进,继承高吞吐优势的同时弥补了Kafka的不足,但客户端以Java为主。 - **RabbitMQ**:基于Erlang开发,吞吐量虽然不及Kafka,但在消息可靠性和低延迟方面表现优秀,支持多种协议和...
- **并发读写冲突**:采用CopyOnWrite技术,先复制实例列表,更新后再替换,保证了并发读写的正确性和数据一致性。 3. **Nacos与Eureka对比** - **接口方式**:两者都提供RESTful API,但Nacos提供了更丰富的功能...
在Tomcat的`conf/context.xml`文件中,添加`<Manager>`元素,并设置`copyOnWrite`和`shared`属性为`true`。 2. **生成独一无二的JVMRoute**:每个Tomcat实例需要一个唯一的ID,这可以通过在`server.xml`中的`Engine...
5. **CopyOnWrite机制**:在某些场景下,如果写操作远少于读操作,可以使用CopyOnWriteArrayList或CopyOnWriteArraySet的思想,复制一个新的BitSet并在新的副本上进行修改,然后在合适的时候替换原BitSet。...