In this tutorial, we will learn how to synchronize ArrayList in Java. We know an ArrayList is a popular dynamic data structure in Java that allows us to store and manipulate a list of objects.
However, ArrayList is not thread-safe, meaning that it is not safe to use it in a multi-threading environment without proper synchronization. In this tutorial, we will discuss two ways to synchronize ArrayList in Java.
Before going to understand this topic, first, we will understand in brief the meaning of synchronization.
What is Synchronization in Java?
Technically, Synchronization in Java is the process of allowing only one thread at a time to complete the task entirely. It allows only one thread to access a single resource or a single task.
When multiple threads access the same resources at the same time then the program may produce an undesirable output. So, this problem can be solved by using a technique known as synchronization. The objective of synchronization is to control access to a shared resource.
We know that by default ArrayList class is not a thread-safe or non-synchronized. That means the multiple threads can access the same ArrayList object or instance simultaneously.
Therefore, it cannot be used in the multi-threading environment without explicit synchronization. This is because if ArrayList is used in the multi-threading environment without using the synchronization technique then it may produce unpredictable output.
So, how will we get synchronized ArrayList in Java with thread safety?
How to Synchronize ArrayList object in Java?
There are two methods by which we can get the synchronized version of ArrayList. They are as follows:
- By using Collections.synchronizedList() method
- By using CopyOnWriteArrayList
Synchronization of ArrayList using Collections.synchronizedList() method
This method is used to synchronize collections in Java. The syntax of this method is as follows:
public static List<T> synchronizedList(List<T> list)
1. The synchronizedList() method accepts List which could be the implementation of List interface. For example, ArrayList, and LinkedList.
2. The return type of this method is a synchronized list (thread-safe).
3. synchronizedList is the name of the method.
4. The parameter list is the list to be wrapped in the synchronize list.
5. T represents the type of generic.
Note:
The Iterator is used in the synchronization block for synchronization to avoid ConcurrentModificationException in Java. The iterator returned by the synchronized ArrayList is fail-fast. It will throw ConcurrentModificationException when any modification happens in the list during the iteration.
Let us write the example code to synchronize ArrayList in Java.
ArrayList<String> al = new ArrayList<String>(); // Non-synchronized. List l = Collections.synchronizedList( al ); l ➟ Synchronized. al ➟ Non-synchronized. or, List<String> synlist = Collections.synchronizedList( new ArrayList<String>);
Similarly, we can get the synchronized version of Set, Map objects by using the following syntax:
public static Set synchronizedList( Set s ); public static Map synchronizedList( Map m );
Let’s take an example program where we will synchronize the list of non-synchronized ArrayList objects and then we will call iterator() method to iterate the list of synchronized ArrayList objects.
Program code 1:
package synchronizeTest; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; public class ArrayListSynchronizationTest { public static void main(String[] args) { // Create an ArrayList object with initial capacity of 10. // Non-synchronized ArrayList Object. List<String> l = new ArrayList<String>(); // Add elements in the list. l.add("Apple"); l.add("Orange"); l.add("Banana"); l.add("Pineapple"); l.add("Guava"); // Synchronizing ArrayList in Java. List<String> synlist = Collections.synchronizedList( l ); // l is non-synchronized. // Here, we will use a synchronized block to avoid the non-deterministic behavior. synchronized(synlist) { // Call iterator() method to iterate the ArrayList. Iterator<String> itr = synlist.iterator(); while(itr.hasNext()) { String str = itr.next(); System.out.println(str); } } } }
Output: Apple Orange Banana Pineapple Guava
In the preceding program, ArrayList achieves thread-safety by calling the synchronizedList() method that locks the whole list into the synchronized block.
Let’s take another program where we will check the occurrence of ConcurrentModificationException by adding a number into the synchronized list during the Iteration.
Program code 2:
package synchronizeTest; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; public class CMETest { public static void main(String[] args) { ArrayList<Integer> al = new ArrayList<Integer>(); for(int i = 0; i < 10; i++) { al.add(i); } List<Integer> synlist = Collections.synchronizedList(al); synchronized(synlist) { Iterator<Integer> itr = synlist.iterator(); while(itr.hasNext()) { al.add(20); // It will throw ConcurrentModificationException because we cannot modify list during Iteration. System.out.println(itr.next()); } } } }
Output: Exception in thread "main" java.util.ConcurrentModificationException
Synchronization of ArrayList using CopyOnWriteArrayList class in Java
1. CopyOnWriteArrayList implements List interface and creates an empty list.
2. It creates a list of the elements in the order of specified collection.
3. It is thread-safe concurrent access of ArrayList. When ArrayList is modified, it will create a fresh copy of the underlying array.
4. Iterator and ListIterator returned by CopyOnWriteArrayList is completely thread-safe. It will not throw ConcurrentModificationException when ArrayList is modified during iteration.
5. CopyOnWriteArrayList does not lock the whole list. When a thread writes into the list, It simply replaces the list by a fresh copy of the underlying array.
In this way, it provides concurrent access of ArrayList for the multiple threads without locking. Since read operation is a thread-safe, two threads cannot write into the list simultaneously.
The syntax to create an object of CopyOnWriteArrayList is as follows:
CopyOnWriteArrayList<T> al = new CopyOnWriteArrayList<T>(); // T is generic.
Let’s write a Java program in which we will synchronize a list of elements in ArrayList using the CopyOnWriteArrayList class.
Program code 3:
package synchronizeTest; import java.util.Iterator; import java.util.concurrent.CopyOnWriteArrayList; public class SynArrayListUsingCOWA { public static void main(String[] args) { // Create a thread-safe ArrayList. CopyOnWriteArrayList<String> al = new CopyOnWriteArrayList<String>(); al.add("Pen"); al.add("Pencil"); al.add("Copy"); al.add("Eraser"); al.add("Shapner"); System.out.println("Displaying synchronized ArrayList "); // Synchronized block is not required in this method. Iterator<String> itr = al.iterator(); while(itr.hasNext()) { String str = itr.next(); System.out.println(str); } } }
Output: Displaying synchronized ArrayList Pen Pencil Copy Eraser Shapner
Let’s write another Java program in which we will try to add an element in the synchronized list during iteration. Here, we will check that CopyOnWriteArrayList will throw ConcurrentModificationException during the iteration or not.
Program code 4:
package synchronizeTest; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; public class AddingTest { public static void main(String[] args) { CopyOnWriteArrayList<String> al = new CopyOnWriteArrayList<String>(); al.add("A"); al.add("B"); al.add(null); al.add("D"); al.add("E"); al.add("H"); System.out.println(al); List<String> synlist = Collections.synchronizedList(al); // Here, Synchronized block is not required. // Call iterator() method using reference variable synlist. Iterator<String> itr = synlist.iterator(); while(itr.hasNext()) { al.set(5, "F"); // It will not throw ConcurrentModificationException during Iteration. String str = itr.next(); System.out.println(str); } System.out.println(al); } }
Output: [A, B, null, D, E, H] A B null D E H [A, B, null, D, E, F]
As you can observe in the above program, during iteration, we can easily add an element in the synchronized list using the CopyOnWriteArrayList method.
In this tutorial, we have covered almost all important points related to the synchronization of ArrayList with examples. Hope that you will have understood the basic concept of how to synchronize ArrayList in Java.
Thanks for reading!!!
Next ⇒ Java ArrayList Program⇐ Prev Next ⇒