Thread-Safe Collections in Java: ConcurrentHashMap vs Synchronized Collections

Mahesh SharmaMahesh Sharma
7 min read

Thread-Safe Collections in Java: ConcurrentHashMap vs Synchronized Collections

Thread safety is a crucial consideration when working with collections in multi-threaded Java programs. ConcurrentHashMap and synchronized collections are two of Java's many thread-safety features. This article provides in-depth comparisons of various alternatives' implementations, performance traits, and suitable use cases.

Version Consideration of Java 8+ for Synchronization Collection uses the single lock approach, and for ConcurrentHashMap, uses improved CAS-based implementation with better contention handling.

Understanding Thread Safety in Collections

Thread safety in collections ensures that a collection can be safely accessed and modified by multiple threads simultaneously without causing data corruption or inconsistent states, whereas concurrent access can lead to race conditions, data corruption, inconsistent states, and a ConcurrentModificationException if it is not synchronized correctly.

The two approaches offered by Java regarding the thread-safety collections. These two approaches are Synchronized Collections and Concurrent Collections.

Synchronized Collections

Synchronized Collections is a type of thread safety collection. It is created with the help of synchronization code by wrapping regular collections with the help of using the factory method named as Collections.synchronizedABC().

Creating Synchronized Collections

List<String> syncList = Collections.synchronizedList(new ArrayList<>());

Map<String, String> syncMap = Collections.synchronizedMap(new HashMap<>());

Set<String> syncSet = Collections.synchronizedSet(new HashSet<>());

Details of Implementation for Synchronized Collection

[if !supportLists]· [endif]The first step into the implementation of the synchronized collection is to work by synchronizing all the methods available on a single lock (single lock considered as a collection of objects itself) and also wraps up the original collections.

[if !supportLists]· [endif]The second step in the implementation is that every operation, such as read/write, contains this type of lock.

[if !supportLists]· [endif]The step in the implementation of the synchronized collection, in which coarse-gained is done by the synchronization under which at a single time only one thread can do the interactions with the collections.

Benefits of Synchronized Collection

There are many benefits of the synchronized collection. Some of the crucial benefits are given below.

[if !supportLists]· [endif]Synchronized Collection is very simple to use as we can just wrap all the existing collections very easily.

[if !supportLists]· [endif]In a process of synchronized collection, the behavior of the method is always considered as consistent in which all the operations such as write/read are synchronized fully.

[if !supportLists]· [endif]Synchronized collections are mostly beneficial for infrequently modified data because when the rate of write operation is rare, then it always impacts the performance by minimizing it.

Drawbacks of Using Synchronized Collections

There are different number of disadvantages discovered while using the synchronized collection, but some of the most important drawbacks that can be compulsory to enlighten. Here are the drawbacks given below:

[if !supportLists]· [endif]One of the most crucial drawbacks of the synchronized collections is poor scalability due to the synchronization of all the methods in a single lock that leads to the creation of contention under heavy load.

[if !supportLists]· [endif]Another drawback of using synchronized collection is operations with no atomic compound. One of the operation names as ‘check-then-act,’ always requires an external synchronization.

[if !supportLists]· [endif]The most favorable drawback of using synchronized collection is the requirement of manual synchronization for iterators. In a synchronized collection, individual operators are thread-safe, while iteration always requires an explicit synchronization.

// Proper iteration requires external synchronization

synchronized(syncMap) {

for (String key : syncMap.keySet()) {

// process key

}

}

How to make a collection thread-safe in Java?

The Collections class contains methods from the Java.util package that only works with collections. These methods provide several additional polymorphic algorithm-based actions. This class provides different versions of the synchronizedCollection() method, as can be seen below. Here, we explain the six methods of synchronized collections.

[if !supportLists]· [endif]static <T> Collection<T> synchronizedCollection(Collection<T> c): It is a variant from one of the methods of synchronizedCollection in which it returns a synchronized collection backed by the specified condition, and it also accepts any type of object collection by ensuring that the synchronized collection should be thread safe.

[if !supportLists]· [endif]static <T> List<T> synchronizedList(List<T> list): It is the second version of the synchronized collection() method, which takes the list of the object and returns for the synchronized list that is also backed up by the specified list. It also ensures the thread-safety of synchronized List.

[if !supportLists]· [endif]static <K,V> Map<K,V> synchronizedMap(Map<K,V> m): It is the third type or version of the synchronizedCollection() method, by using an Map interface it takes an object and as same as above returns the synchronized map that was backed up by the specified map by ensuring that synchronized map should be thread-safe.

[if !supportLists]· [endif]static <T> Set<T> synchronizedSet(Set<T> s): This the fourth version or variant of the synchronizedCollection() method, about the set interface it accepts an objects and then returns them in a way synchronized set that is also backed up by the specified set by ensuring that synchronized set should be thread-safe.

[if !supportLists]· [endif]static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m): It is the fifth version of the synchronizedcollection() method that focuses on accepting the values as an object under the recognized map interface and then returns a synchronized sorted map that is also backed up by the specified sorted map which also ensures the thread-safety of the synchronized sorted map.

[if !supportLists]· [endif]static <T> SortedSet<T> synchronizedSortedSet(SortedSet<T> s): It is the last and sixth version of the synchronizedcollections() method. It is mainly a combination of the sorted map and set, which is written as a synchronized SortedSet interface in which method is accepted as an object and then returns a synchronized sorted set that is also backed up by the specified sorted set by remembering the thread-safety of the sorted set.

ConcurrentHashMap

Java's ConcurrentHashMap is a thread-safe implementation of the Map interface. It allows several threads to read and write data simultaneously and does away with the requirement to lock the entire map. Unlike a regular hash map, which is not thread-safe, a concurrent hash map ensures that the operations are. This makes it ideal for scenarios where modification of the map and the need to access multiple threads happens simultaneously.

Key Point of ConcurrentHashMap

There are multiple key related points present regarding the concurrent hash map. Some of the important key terms are:

[if !supportLists]· [endif]ConcurrentHashMap prevents the entire map from being locked while offering thread-safe operations.

[if !supportLists]· [endif]ConcurrentHashMap makes it possible for several threads to run simultaneously by segmenting the map.

[if !supportLists]· [endif]16 is the default concurrency level of ConcurrentHashMap.

[if !supportLists]· [endif]Some of the atomic operations, such as remove(), replace(), and putIfAbsent() is supported by ConcurrentHashMap.

[if !supportLists]· [endif]ConcurrentHashMap does not allow null objects to be inserted as keys or values.

Declaration of ConcurrentHashMap

ConcurrentHashMap<KeyType, ValueType> map = new ConcurrentHashMap<>();

Advantages of ConcurrentHashMap

There are many benefits of using a ConcurrentHashMap that cover the important points, features, factors, and characteristics of a ConcurrentHashMap. Some of the benefits are:

[if !supportLists]· [endif]ConcurrentHashMap is scalable as it always performs well under heavy contention also.

[if !supportLists]· [endif]The most crucial benefit of using ConcurrentHashMap is safe iteration because it does not throw iterators. ConcurrentModificationException.

[if !supportLists]· [endif]Fine-grained locking is also considered an essential benefit of ConcurrentHashMap. In this, only portions of the given map are locked during the process of updating.

[if !supportLists]· [endif]Atomic operations are considered one of the most important features of ConcurrentHashMap, which has a system of built-in support for common compound operations.

[if !supportLists]· [endif]The most important key factor of ConcurrentHashMap in terms of benefits is higher throughput in multiple numbers of threads is able to write and read concurrently.

Disadvantages of ConcurrentHashMap

There are different numbers of drawbacks in ConcurrentHashMap due to which loopholes are present in the features, factors, and key characteristics. Some of the most highlighted drawbacks are:

[if !supportLists]· [endif]The most reasonable drawback of ConcurrentHashMap is overhead with more memory. It happens in the concurrent hash mapping due to the internal segmentation.

[if !supportLists]· [endif]Another drawback of using ConcurrentHashMap can be size and isEmpty() should be approximate. These are the different types of methods used in the process of thread safety. They are not locked and may always return an approximate result.

[if !supportLists]· [endif]Implementations of ConcurrentHashMap are more complex and more demanding to understand in their internal workings.

Key Differences between Synchronized Collection and ConcurrentHashMap

FeaturesSynchronized CollectionsConcurrentHashMap
ScalabilityPoorExcellent under contention
Memory OverheadLessModerate
Locking MechanismSingle locksStriped locks or CAS operations
Iterator BehaviorRequires external synchronization, Fail-fastDoesn’t fail, poorly consistent
Atomic OperationsNot providedBuilt-in (compute, putlfabsent, etc)
Null ValuesAllowedNot allowed
Write PerformanceOnly one synchronized writer at a timeMultiple concurrent writers at a time is possible
Read PerformanceIt is blocked during writes.Non-blocking reads

Conclusion

The ConcurrentHashMap and Synchronized Collections provide thread safety but with the variation of different features, demand, factors, and characteristics:

Synchronized Collections: Throughout the process of complete synchronization, synchronization collection offers a simple thread-safety but always suffers in terms of scalability issues.

ConcurrentHashMap: Throughout the CAS operations and sophisticated striping of locks, ConcurrentHashMap provides superior performance in a concurrent environment.

0
Subscribe to my newsletter

Read articles from Mahesh Sharma directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Mahesh Sharma
Mahesh Sharma