WalzoneInterview Prep
📞 Interviewing soon? Practice with a realistic AI mock phone interview — it calls you, then scores you. First 15 min FREE →

Java Concurrency · Expert · question 63 of 100

How does the Java synchronized keyword work with different JVMs and CPU architectures?

📕 Buy this interview preparation book: 100 Java Concurrency questions & answers — PDF + EPUB for $5

The synchronized keyword in Java provides a way to ensure mutual exclusion in multi-threaded code by preventing multiple threads from executing the synchronized code block or method simultaneously. When a thread enters a synchronized block, it acquires the intrinsic lock associated with the object that the block is synchronized on, and other threads that attempt to enter the same block will be blocked until the lock is released by the first thread.

The way that the synchronized keyword works with different JVMs and CPU architectures can have a significant impact on performance. In general, modern JVMs and CPUs are optimized to provide efficient synchronization, but there are still some differences that can affect performance.

On some older JVMs or CPUs, acquiring and releasing a lock can be relatively expensive, and so it is important to minimize the number of synchronized blocks that are used. Lock coarsening and lock splitting are two techniques that can be used to optimize synchronization in some cases.

Lock coarsening involves combining multiple small synchronized blocks into a single larger block in order to reduce the overhead of acquiring and releasing locks. For example, if a method has two small synchronized blocks that operate on the same object, it may be more efficient to combine them into a single larger block that encompasses both operations.

Lock splitting involves breaking a large synchronized block into smaller blocks in order to reduce contention for the lock. For example, if a method has a large synchronized block that operates on multiple objects, it may be more efficient to split the block into smaller blocks that operate on individual objects, so that threads can access different objects without having to wait for each other to release the lock.

Here’s an example that illustrates the use of lock coarsening and lock splitting:

public class SynchronizedExample {
    private final Object lock1 = new Object();
    private final Object lock2 = new Object();

    public void synchronizedMethod1() {
        synchronized (lock1) {
            // ...
        }
        synchronized (lock2) {
            // ...
        }
    }

    public void synchronizedMethod2() {
        synchronized (lock1) {
            // ...
        }
        synchronized (lock2) {
            // ...
        }
    }

    public void synchronizedMethod3() {
        synchronized (lock1) {
            // ...
        }
    }
}

In this example, there are three synchronized methods that use two different locks (lock1 and lock2). synchronizedMethod1() and synchronizedMethod2() both use both locks, while synchronizedMethod3() only uses lock1.

If profiling shows that acquiring and releasing locks is a significant bottleneck in this code, we could consider applying lock coarsening and/or lock splitting. For example, we could coarsen the code like this:

public void synchronizedMethod1And2() {
    synchronized (lock1) {
        // ...
        // ...
        // ...
    }
    synchronized (lock2) {
        // ...
        // ...
        // ...
    }
}

public void synchronizedMethod3() {
    synchronized (lock1) {
        // ...
    }
}

By combining the two blocks that use both locks into a single block, we reduce the number of lock acquisitions and releases, which can improve performance.

Alternatively, if contention for lock1 is a bottleneck, we could split the code like this:

public void synchronizedMethod1() {
    synchronized (lock1) {
        // ...
    }
    synchronized (lock2) {
        // ...
    }
}

public void synchronizedMethod2() {
    synchronized (lock1) {
        // ...
    }
    synchronized (lock2) {
        // ...
    }
}

public void synchronizedMethod3() {
    synchronized (lock1) {
        // ...
    }
}
Reading is step one. Saying it out loud is the interview. Our AI interviewer calls your phone and runs a realistic Java Concurrency interview — then scores it.
📞 Practice Java Concurrency — free 15 min
📕 Buy this interview preparation book: 100 Java Concurrency questions & answers — PDF + EPUB for $5

All 100 Java Concurrency questions · All topics