Article start
Java Backend Interview Prep
2. Backend Architecture & Data

6. Advanced Java Concurrency for Interviews

Go beyond basic threads into volatile, synchronization, atomics, and thread-safe collections.

May 29, 2026·21

Creating Threads

Java can create work using Thread, Runnable, Callable, and executors. Implementing Runnable is often preferred over extending Thread because Java supports only one concrete superclass.

Visibility vs Mutual Exclusion

volatile gives visibility: reads see the latest written value. It does not make compound operations like count++ atomic.

synchronized gives mutual exclusion and visibility by acquiring and releasing a monitor lock.

Thread-Safety Strategies

StrategyExample
Stateless designNo shared mutable fields
Immutabilityfinal fields, no setters
Thread-local stateThreadLocal<T>
Atomic classesAtomicInteger, AtomicReference
Concurrent collectionsConcurrentHashMap, CopyOnWriteArrayList

Interview Warning

Do not say volatile is a replacement for synchronized. Volatile is excellent for flags; synchronized or atomic classes are needed for safe compound updates.

Concurrency Code Examples

volatile for Visibility

class Worker {
    private volatile boolean running = true;

    public void stop() {
        running = false;
    }

    public void run() {
        while (running) {
            // work until another thread changes the flag
        }
    }
}

synchronized for Mutual Exclusion

class Wallet {
    private int balance;

    public synchronized void deposit(int amount) {
        balance += amount;
    }

    public synchronized int getBalance() {
        return balance;
    }
}

AtomicInteger for Safe Counters

class VisitCounter {
    private final AtomicInteger count = new AtomicInteger();

    public int increment() {
        return count.incrementAndGet();
    }
}

Interview Scenario Practice

Scenario 1: Stop Flag Not Seen by Worker Thread

Scenario: One thread sets a boolean stop flag to false, but another thread keeps running.

Strong answer: Use volatile for a simple visibility flag, or use higher-level cancellation tools when working with executors.

Why it works: volatile tells Java that reads should see the latest write from main memory.

Common mistake: Thinking volatile makes all operations atomic. It does not.

Scenario 2: HashMap Frequency Counter Failed

Scenario: A HashMap frequency counter gives wrong counts when multiple threads update it.

Strong answer: A normal HashMap is not thread-safe, and get then put is a compound operation. Use ConcurrentHashMap with merge, synchronize the critical section, or use atomic counters.

Why it works: Concurrent updates need atomicity, not just visibility.

Common mistake: Adding volatile to the map reference and expecting the internal updates to become safe.

Scenario 3: Shared Counter Under Load

Scenario: A shared count++ loses increments during load testing.

Strong answer: Use AtomicInteger.incrementAndGet(), LongAdder for high-contention counters, or a synchronized block when the update belongs to a larger critical section.

Why it works: count++ is read, add, and write. Those steps can interleave across threads.

Common mistake: Saying an int update is always safe because reading an int is small.

Discussion

0 comments

Sign in to share a question or add to the discussion.
Start the discussion

Ask a question or share what stood out to you.