Tuesday, 1 March 2016

CopyOnWriteArraySet in Java Concurrency

In Java 5 many concurrent collection classes are added as a thread safe alternative for their normal collection counterpart which are not thread safe. Like ConcurrentHashMap as a thread safe alternative for HashMap, CopyOnWriteArrayList as a thread safe alternative for ArrayList. Same way CopyOnWriteArraySet is added as a thread safe alternative for HashSet.

CopyOnWriteArraySet

CopyOnWriteArraySet implements the set interface (Actually it extends the AbstractSet class which in turn implements the set interface). Since CopyOnWriteArraySet implements the set interface so basic functionality of the set that only unique elements can be added stays intact. CopyOnWriteArraySet also has an add() method -

add(E e) - Adds the specified element to this set if it is not already present.

CopyOnWriteArraySet is thread-safe

As already mentioned CopyOnWriteArraySet is thread-safe and one thing to note here is that it is backed by CopyOnWriteArrayList which means CopyOnWriteArraySet internally uses CopyOnWriteArrayList for all of its operations.

Since it uses CopyOnWriteArrayList internally so thread-safety is achieved in the same way in CopyOnwriteArraySet as in CopyOnWriteArrayList - all mutative operations (add, set, and so on) are implemented by making a fresh copy of the underlying array.

Since fresh copy is made every time for a mutative operation so CopyOnWriteArraySet is more useful in the scenarios where set sizes generally stay small, read-only operations vastly outnumber mutative operations, and you need to prevent interference among threads during traversal.

As example when you have a unique set of values, which are read more by threads and operations like add or set are very rarely used, CopyOnWriteArraySet would be a good choice.

CopyOnWriteArraySet iterator

The iterator returned by CopyOnwriteArraySet is fail-safe which means any structural modification (Structural modifications are those that change the size of the collection or otherwise perturb it in such a fashion that iterations in progress may yield incorrect results) made to the CopyOnwriteArraySet won't throw ConcurrentModificationException.

The iterator returned by concurrent collections like CopyOnWriteArrayList or CopyOnWriteArraySet uses the "snap-shot" style iterator. The "snapshot" style iterator method uses a reference to the state of the array at the point that the iterator was created. This array never changes during the lifetime of the iterator, so interference is impossible and the iterator is guaranteed not to throw ConcurrentModificationException. The iterator will not reflect additions, removals, or changes to the list since the iterator was created. Note that in case of CopyOnWriteArraySet Iterators do not support the mutative remove operation. Any attempt to use iterator's remove() method will result in UnsupportedOperationException.

Example of CopyOnWriteArraySet with iterator

In this code we'll try to iterate a CopyOnWriteArraySet and also create a thread which will try to add new element to the set simultaneously.

public class CWSDemo {

    public static void main(String[] args) {
        Set<Integer> numSet = new CopyOnWriteArraySet<Integer>();
        // Adding 5 elements to the set
        for(int i=1;i<=5;i++) {
            numSet.add(i);
        }
        // Creating new thread
        new Thread(new Runnable(){
            @Override
            public void run() {
                try {
                    // introducing some delay
                    Thread.sleep(150);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
                // add new element to the set
                numSet.add(6);
                System.out.println("" + numSet);
            }
        
        }).start();
        
        // get an iterator
        Iterator<Integer> itr = numSet.iterator();
        while(itr.hasNext()){
            Integer i = itr.next();
            try {
                Thread.sleep(30);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            //itr.remove();
            System.out.println("" + i);
        }
    }
}

Output

1
2
3
4
[1, 2, 3, 4, 5, 6]
5

Here it can be seen that the thread adds a new element at the same time when the CopyOnWriteArraySet is iterated, still ConcurrentModificationException is not thrown. Since iterator get its own copy to iterate so the change is not reflected in that copy and the set still display elements 1-5 only.

If you uncomment the line itr.remove(); in the code it will throw UnsupportedOperationException when executed.

Output

Exception in thread "main" java.lang.UnsupportedOperationException at 
java.util.concurrent.CopyOnWriteArrayList$COWIterator.remove(Unknown Source) 
at org.netjs.prgrm.CWSDemo.main(CWSDemo.java:42)
[1, 2, 3, 4, 5, 6]

That's all for this topic CopyOnWriteArraySet in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Difference between HashMap and ConcurrentHashMap in Java
  2. ArrayBlockingQueue in Java Concurrency
  3. ReentrantLock in Java concurrency
  4. CyclicBarrier in Java concurrency
  5. Phaser in Java concurrency
  6. Java Concurrency interview questions

You may also like -

2 comments:

  1. Everything is fine, am happy about your blog. Thanks admin for sharing the unique content, you have done a great job I appreciate your effort and I hope you will get more positive comments from the web users.

    Regards,
    Aamala

    SEO Training in Chennai

    ReplyDelete
  2. Awesome article about concurrent collection. My doubt has been cleared after visiting this site.
    Thanks for a great effort.

    ReplyDelete