Java 集合中同步ArrayList和CopyOnWriteArrayList的区别

Java 集合中同步ArrayList和CopyOnWriteArrayList的区别

我们知道ArrayList是不同步的,如果多个线程试图同时修改ArrayList,那么最后的结果将是不确定的。因此,为了在多线程环境下实现线程安全,同步ArrayList是必须的。

为了创建List对象,我们一般都是创建List接口的对象,然后根据我们的要求创建List类,并在最近添加元素,进行访问和更新,而没有考虑到线程安全问题。这个概念很简单,同时也有点高级,因为我们看到大多数Java开发者在编写代码时并没有采用这种技术。

注意: 同步ArrayList是同步集合,而 CopyOnWriteArrayList是一个并发集合,因为它是在保持并发性的情况下产生的。

在ArrayList中实现同步的不同方法

ArrayList中的同步可以通过两种方式实现。

  1. 使用集合类的synchronizedList()方法
  2. 使用CopyOnWriteArrayList(COWAL)。

例子

// Java Program to Illustrate Synchronized ArrayList
// Using synchronizedList() Method
 
// Importing required classes
import java.util.* ;
 
// Main class
// SynchronizedArrayList
class GFG {
 
    // Main driver method
    public static void main(String[] args) {
 
        // Creating an empty ArrayList of string type
        // By default, non - synchronized List
        List<String> sal = new ArrayList<String>();
 
        // Adding elements to above List
        // using add() method
        sal.add("Geeks");
        sal.add("for");
        sal.add("Geeks");
        sal.add("Computer");
        sal.add("Science");
        sal.add("Portal");
 
        // Printing the above non-synchronised List
        System.out.println(sal);
 
        // Synchronizing above List
        // using SynchronizedList() method
        Collections.synchronizedList(sal);
 
        // Synchronized block to
        // avoid non-deterministic behavior
        synchronized (sal) {
 
            // Using iterators to iterate over elements
            Iterator<String> itrobj = sal.iterator();
 
            // Holds true till there is single element remaining
            while (itrobj.hasNext()) {
                // Printing elements
                // using next() method
                System.out.println(itrobj.next());
            }
        }
    }
}
Java

输出

Java集合中同步ArrayList和CopyOnWriteArrayList的区别

由于这两种方法都是用来实现Arraylist的线程安全的。问题出现了,何时使用COWAL,何时使用Collections类的synchronizedList()方法。这可以通过了解它们之间的区别来理解。 synchronized ArrayList和CopyOnWriteArrayList之间的主要区别来自于它们的性能、可扩展性以及它们如何实现线程安全。

当Collection.synchronizedList()已经存在时,为什么CopyOnWriteArrayList会出现?

所以答案很简单,因为最初,SynchronizedList被用于多线程环境,但它有一些限制。它所有的读写方法都是同步于列表对象本身的,也就是说,如果一个线程正在执行add()方法,它就会阻止其他想要获得迭代器的线程访问列表中的元素。另外,每次只允许一个线程对列表中的元素进行迭代,这是不高效的。这是很僵硬的。因此,需要一个更灵活的集合,允许。

  1. 多个线程同时执行读操作。
  2. 一个线程执行读操作,另一个线程同时执行写操作。
  3. 只有一个线程可以执行写操作,而其他线程可以同时执行读操作。

为了克服这些问题,最后,在 Java 5 中,引入了一组新的集合类,称为 并发集合 ,其中有 CopyOnWriteArrayList 。CopyOnWriteArrayList类是为了实现这种顺序写和并发读的功能。

让我们来讨论一下与这两个类相关的特性,它们之间有一条细微的区别,如下所示。

1.线程的锁定

CopyOnWriteArrayList 类的工作原理与它的名字一样,即写时复制(copy-on-write ),在读和写的操作中执行不同的操作。对于每一个写操作(add、set、remove等),它都会为列表中的元素制作一个新的副本,而对于读操作(get、iterator、listIterator等),它在一个不同的副本上工作。因此,在读操作中没有额外的开销,它的读操作比Collections.SynchronizedList()快。因此, COWAL比Synchronized List更适合于读取操作

2.写操作

对于ArrayList的写操作, COWAL的写操作比Collections.synchronizedList()慢, 因为它使用了Re-entrantLock。写入方法总是创建一个现有数组的副本,并在副本上进行修改,最后更新数组的易失性引用以指向这个新数组。因此,在写操作中,它有大量的开销。这就是为什么CopyOnWriteArrayList的写操作要比Collections.synchronizedList()慢。

3.修改过程中的行为

Synchronized List是一个快速失败的迭代器 ,也就是说,当一个线程在列表上迭代时,它将抛出ConcurrentModifcationException,而 CopyOnWriteArrayList是一个失败安全的迭代器 ,也就是说,即使一个线程在列表上迭代时,它也不会抛出ConcurrentModifcationException。

4.工作线程的数量

只有一个线程被允许在同步列表上操作,通过锁定整个列表对象,这影响了它的性能,因为其他线程在等待,而在 COWAL 的情况下,多个线程被允许在ArrayList上操作,因为它在单独的克隆副本上进行更新/修改操作,这 使得它的性能更快。

5.块内迭代

当迭代同步List时,确保在同步块内迭代,而在CopyOnWriteArrayList中,我们可以安全地在同步块外迭代。

什么时候使用SynchronizedList

  • 因为在CopyOnWriteArrayList中,每一次更新/修改操作都会创建一个新的单独的克隆副本,JVM分配内存并将克隆副本与原始副本合并的开销很大。因此,在这种情况下,SynchronizedList是一个更好的选择。当Arraylist的大小很大时。
  • 当Arraylist的大小很大时。

什么时候使用CopyOnWriteArrayList

  • CopyOnWriteArrayList提供了无锁的读取,这意味着如果有更多的读者线程,并且写入发生率很低,那么性能会好很多。
  • 当Arraylist的大小较小时。

SynchronizedList v/s CopyOnWriteArrayList

SynchronizedArrayList CopyOnWriteArrayList
在Java 1.2版本中引入 在Java 1.5版本中被引入
当写操作多于读操作时,就应该使用它。 当读操作多于写操作时,应该使用它。
使用的迭代器是故障快速的。 使用的迭代器是故障安全的。
List的迭代必须存在于同步块内。 列表的迭代可以在同步块之外。
整个ArrayList被Synchronized Arraylist锁定,以便在读和写操作中保证线程安全。 整个ArrayList被SynchronizedArrayList锁定,以便在写操作中保证线程安全。
当ArrayList较大时,它是首选。 当ArrayList较小时,它是首选。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程

登录

注册