Concurrent Collections

Besides concurrent collections, Concurrency API also includes methods for obtaining synchronized versions of existing non-concurrent collection objects. These methods, defined in Collections class, contain synchronized methods that operate on the inputted collection and return a reference that is the same type as the underlying collection. Methods are listed in table :

Method Name
synchronizedCollection(Collection<T> c)
synchronizedList(List<T> list)
synchronizedMap(Map<K, V> m)
synchronizedNavigableMap(NavigableMap<K, V> m)
synchronizedNavigableSet(NavigableSet<T> s)
synchronizedSet(Set<T> s)
synchronizedSortedMap(SortedMap<K, V> m)
synchronizedSortedSet(SortedSet<T> s)

If it is known at the time of creation that object requires synchronization, then one of the concurrent collections listed above is a better choice. On the other hand, if developer is given an existing collection that is not a concurrent class and needs to be accessed among multiple threads, it can be wrapped using one of the methods above.

While the methods for obtaining synchronized versions synchronize access to the data elements, such as get() and set() methods, they do not synchronize access on any iterators that can be created from the synchronized collection. Therefore, it is imperative to use synchronization block for iterating over any of the returned collections. See example below :

public class SynchronizedListExample {
    public static void main(String[] args) {
        List<Integer> list = Collections.synchronizedList(new ArrayList<>(Arrays.asList(4,3,52)));

        synchronized (list) {
            for (int data : list) {
                System.out.print(data + " ");
            }
        }
    }
}

Unlike the concurrent collections, the synchronized collections also throw an exception if they are modified within an iterator by a single thread. The code above

public class SynchronizedListConcurrentModificationExample {
public static void main(String[] args) {
Map<String, Object> foodData = new HashMap<>();
foodData.put("penguin", 1);
foodData.put("flamingo", 2);
Map<String, Object> synchronizedFoodData = Collections.synchronizedMap(foodData);
for (String key : synchronizedFoodData.keySet()) {
synchronizedFoodData.remove(key);
}
}
}

throws a ConcurrentModificationException at runtime, whereas example with ConcurrentHashMap would not. Other than iterating over the collection, the objects returned by the methods in above table are inherently safe to use among multiple threads.

Previous

Leave a Reply

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