Copy-on-Write Collections – Concurrency: Part II

Copy-on-Write Collections

The copy-on-write collections comprise special-purpose concurrent lists and sets that are recommended when read operations vastly outnumber mutative operations on the collection. The classes CopyOnWriteArrayList and CopyOnWriteArraySet implement the List and the Set interfaces in the java.util package (Figure 23.7). A summary of the copy-on-write classes in the java.util.concurrent package is given in Table 23.15. Salient characteristics of these collections are summarized in Table 23.16.

Figure 23.7 Copy-on-Write Collections in the java.util.concurrent Package

Table 23.15 Copy-on-Write Collections in the java.util.concurrent Package

Copy-on-write collectionsDescription
CopyOnWriteArrayList<E> implements List<E>A thread-safe variant of ArrayList in which all mutative operations (add, set, etc.) are implemented by making a fresh copy of the underlying array.
CopyOnWriteArraySet<E> implements Set<E>A Set that uses an internal CopyOnWriteArrayList for all of its operations.

Table 23.16 Characteristics of Copy-on-Write Collections

Copy-on-write collectionsnull valueDuplicatesOrderingKind of iterator
CopyOnWriteArrayList<E> implements List<E>YesYesInsertion orderSnapshot-style
CopyOnWriteArraySet<E> implements Set<E>YesNoNo orderSnapshot-style

The CopyOnWriteArrayList<E> Class

The CopyOnWriteArrayList class implements the java.util.List interface (§15.3, p. 801), providing a thread-safe list that is recommended for a vast number of concurrent read and traversal operations. It uses an underlying array to implement its operations. By default, such a list is immutable, guaranteeing thread-safety of concurrent operations. Any mutative operation (add, set, remove, etc.) is done on a new copy of its entire underlying array which then supersedes the previous version for subsequent operations. For efficiency reasons, the list size should be kept small and modifications should be minimized, as they are expensive, incurring the copying cost of its underlying array and extra space.

Traversal via snapshot-style iterators is efficient and thread safe—there is no need for any external synchronization, since it relies on the immutable state of the underlying array at the time the iterator is constructed (Example 23.21). Note that immutability of the list during traversal rules out the remove() operation of the iterator, as this can invalidate its snapshot traversal guarantee if allowed. In the code below, the Iterator.remove() method at (2a) results in an UnsupportedOperation-Exception, whereas the List.remove() method is allowed since it will be performed on a new copy of the underlying array. Note that a thread-unsafe ArrayList instance would allow both (2a) and (2b).

Click here to view code image

List<Integer> cowlist = new CopyOnWriteArrayList<Integer>();          // (1a)
cowlist.addAll(Arrays.asList(10, 20, 30));
Iterator<Integer> iter = cowlist.iterator();
while (iter.hasNext()) {
  Integer i = iter.next();
  if (i == 20) {
//  iter.remove();                      // (2a) UnsupportedOperationException
    cowlist.remove(i);                  // (2b) OK
    continue;
  }
  System.out.print(i + ” “);            // With (2b): 10 30
}

In addition to the methods of the List interface, the following useful methods are also defined by the CopyOnWriteArrayList class:

boolean addIfAbsent(E e)

Appends the element, if not present.

Click here to view code image

int addAllAbsent(Collection<? extends E> c)

Appends to the end of this list all of the elements in the specified collection that are not already contained in this list.

Leave a Reply

Your email address will not be published. Required fields are marked *.

*
*
You may use these <abbr title="HyperText Markup Language">HTML</abbr> tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>