ProgrammingBackend Developer

Describe how the synchronized block works in Java. What are its features, how to choose an object for synchronization, and how can incorrect choices lead to errors?

Pass interviews with Hintsage AI assistant

Answer.

synchronized is a keyword that allows for thread-safe access to critical sections of code. It can be used for either a method (for example, public synchronized void foo()) or for a block of code (synchronized(obj) { ... }). When a thread enters a synchronized block, it acquires the monitor (lock) of the object. While the monitor is occupied, other threads cannot enter another synchronized block that uses the same object as a monitor.

Features:

  • Synchronizing on the same object ensures mutual exclusion (only one thread can execute the block at a time).
  • Synchronization can be done on this, a static object (e.g., the class itself), or any arbitrary object.
  • If a monitor is chosen that is accessible to multiple threads or, conversely, too localized, it can violate thread safety.

Example of choosing a synchronization object

public class Counter { private int count; private final Object lock = new Object(); // private object public void increment() { synchronized(lock) { count++; } } }

Why is it better to use a private lock? Because if you synchronize on a public object (for example, on this or on a public string), external code may also acquire this monitor, leading to deadlocks or incorrect behavior.

Trick Question.

Question: What will happen if you synchronize on a String object that contains a fixed value?

Answer: Strings in Java are interned (the same objects for the same literals). If you synchronize on a string like synchronized("lock"), you may accidentally intersect with other code that synchronizes on the same literal, which will lead to unexpected blocking between completely different parts of the program.

Example (do not do this):

synchronized("LOCK") { ... }

Real error examples due to lack of understanding of the topic.


Story

In a multi-threaded trading system, public objects were used for synchronization, and external code was able to acquire the lock, leading to temporary deadlocks between threads from different modules and delays on the exchange.


Story

A young developer synchronized access to a collection using a string literal. Another part of the code also synchronized on a string with the same value. These threads queued behind each other, causing a severe slowdown in business logic.


Story

A new object was chosen each time for synchronization: synchronized(new Object()) { ... }. As a result, synchronization did not work at all, and different threads had simultaneous access to the data. This was discovered only during load testing.