Java’s Synchronized Collections
Tags: java, tutorial, beginners, programming
Published: 2024-03-30 06:16:14

Java’s Collection framework is one of the foundational components of Java platform. Collections in Java represent a group of objects and the framework provides several interfaces and implementations to work with these collections. With such a rich framework at disposal, developers can focus on what matters the most!

With the advent of multi-threaded programming, the need for thread-safe collections grew. It is when _Synchronized Collections_ were added to Java’s Collection framework. Let us understand what makes Synchronized Collections thread-safe and what are some things we should keep in-mind while using them.

### How does Synchronized Collections ensure thread-safety?
Synchronized collections achieves thread-safety by enforcing synchronization on each of its publicly available method. In addition to that, it ensures that its internal state is never published. Thus, the only way to modify a collection is via its public synchronized methods!

> _Think of synchronized collections as plain unsynchronised collections plus state encapsulation and synchronized public methods._

Since every public method of a synchronized collection is guarded by the same (intrinsic) lock, no two threads can modify/read the collection at once. This ensures that the collection always maintain its variants and hence become thread-safe.

### How to create Synchronized Collections?
The `Collections` class expose several static methods for creating synchronized collections. These static method are named in the following format — `synchronizedXxx`. Here is a list of these methods:
* **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)

This is how you will create a synchronized list using the Collections class!

```java
List<Integer> synchronizedIntegerList = Collections.synchronizedList(new ArrayList<>());
```

### Pitfall of Compound Actions on Synchronized Collections
While methods exposed from synchronized collections are thread-safe, compound actions on client-side still require proper locking. Consider the following method —

```java
public void putIfAbsent(List<Integer> synchronizedList, Integer elem) {
  if(!synchronizedList.contains()) {
    synchronizedList.add(elem);
  }
}
```

This innocent looking method is actually **thread-unsafe**! Even with thread-safe `contains` and `add` methods, the `putIfAbsent` method does not achieve what it intended to. Between the ‘_check_’ and ‘_act_’ steps of our method, another thread can add the `elem` to the list. Guarding such compound actions is the responsibility of the client.

Synchronized collections allow client-side locking to ensure that such compound actions are atomic with respect to other operations. Each public method of the synchronized collection is guarded by its own intrinsic lock. It is thus possible for client to create atomic operation by acquiring the same lock.

Here is how we will fix putIfAbsent using client-side locking.

```java
public void putIfAbsent(List<Integer> synchronizedList, Integer elem) {
  synchronized(synchronizedList) {
    if(!synchronizedList.contains()) {
      synchronizedList.add(elem);
    }
  }
}
```

### Pitfalls of Iterating on Synchronized Collections
Some extra care is needed to be taken when iterating over a synchronized collection. When iterating over a synchronized collection using iterators, any concurrent modifications to the collection will cause the iterator to _fail-fast_. On detecting any concurrent modification, the iterator will throw a ConcurrentModificationException.
```java
final Set<String> syncStringSet = Collections.synchronizedSet(new HashSet<>());

// Might throw ConcurrentModificationException
for(String s: syncStringSet) {
  doSomething(s);
}
```

To avoid getting a `ConcurrentModificationException`, we can hold a lock on the synchronized collection for the entire duration of iteration. Clearly this is not the most performant approach since the iteration can take a long time and it will block other executing threads from access to the collection!

---

Synchronized classes provides an easy mechanism to make your collection classes thread-safe. A thorough understanding of these would help you avoid common pitfalls associated with it.

With this we reach the end of this blog. I hope you enjoyed reading this piece.

If you like reading such articles, here are some other interesting reads from this series —
* _[Object Sharing in Multi-Threaded environment](https://medium.com/@the_infinity/object-sharing-in-multi-threaded-environments-d03d2543e210)_
* _[Visibility Across Threads](https://medium.com/@the_infinity/visibility-across-threads-e13119e8d685)_
* _[Thread Safety from an Object Oriented Perspective](https://medium.com/@the_infinity/thread-safety-from-an-object-oriented-perspective-2913b1879d0c)_
* _[A Nice Race Condition](https://medium.com/@the_infinity/a-nice-race-condition-58a560e34cec)_
* _[Producer-Consumer pattern using Java’s Blocking Queue](https://medium.com/@the_infinity/producer-consumer-pattern-using-javas-blocking-queues-06d147d3c38a)_