10 Must‑Know Java Concurrency Interview Questions
This article walks through ten essential Java concurrency interview topics—including the Java Memory Model, volatile semantics, synchronized lock upgrades, CAS pitfalls, AQS internals, ReentrantLock versus synchronized, ThreadPoolExecutor parameters, ThreadLocal memory‑leak issues, CountDownLatch vs CyclicBarrier, and deadlock conditions—providing code snippets, tables and detailed explanations to help candidates answer interview questions confidently.
Java concurrency is a key differentiator for senior developers, and interviewers often probe deep into this area. This article presents ten high‑frequency interview questions and detailed answers.
1. What is the Java Memory Model (JMM)?
JMM defines the read/write rules for shared variables in multithreaded Java programs. Its three core elements are:
Visibility : a write by one thread becomes immediately visible to others.
Atomicity : a group of operations either all execute or none do.
Ordering : instructions are not reordered. private volatile boolean running = true; The happens‑before relation consists of eight rules (program order, monitor lock, volatile write→read, thread start, thread termination, thread interruption, object finalization, transitivity).
2. How does volatile work?
volatileguarantees visibility and ordering but not atomicity.
Before a volatile write, the JVM inserts a memory barrier that flushes the CPU cache to main memory.
After a volatile read, the value is fetched from main memory, invalidating the local cache.
Typical use cases: boolean flags, double‑checked locking, and read‑many/write‑few scenarios.
3. What is the lock‑upgrade process of synchronized (JDK 1.6+)?
Locks transition only upward: no lock → biased lock → lightweight lock → heavyweight lock . The states are:
No lock : object just created.
Biased lock : stores thread ID in the Mark Word; low overhead.
Lightweight lock : uses CAS with adaptive spinning; moderate overhead.
Heavyweight lock : falls back to OS mutex; high overhead.
4. What is CAS and what problems does it have?
CAS (Compare‑And‑Swap) is a CPU atomic instruction with three parameters: memory location V, expected value E, and new value N. It succeeds when V == E, updating V to N.
Three major issues:
ABA problem : the value may change from A→B→A unnoticed. Solution: AtomicStampedReference with version stamps.
Long spin time : failed spins waste CPU; mitigate by limiting spin attempts or backing off.
Single‑variable limitation : cannot atomically update multiple variables; use AtomicReference to wrap objects.
AtomicStampedReference<String> ref = new AtomicStampedReference<>("A", 0);
int stamp = ref.getStamp();
ref.compareAndSet("A", "B", stamp, stamp + 1);5. What is the core principle of AQS?
AbstractQueuedSynchronizer (AQS) underpins Java’s lock framework. Its core consists of a volatile int state and a CLH queue (a doubly‑linked list of waiting nodes). Subclasses implement tryAcquire and tryRelease to manipulate the state.
┌─────────────────────────────────────┐
│ AQS core structure │
├─────────────────────────────────────┤
│ state (volatile int) // 0: unlocked, 1: locked │
│ CLH queue (head ↔ … ↔ tail) │
│ tryAcquire / tryRelease (subclass) │
└─────────────────────────────────────┘Lock acquisition tries tryAcquire; on failure the thread joins the wait queue and may spin or block.
6. Differences between ReentrantLock and synchronized
Lock release: synchronized releases automatically; ReentrantLock requires explicit unlock() (usually in finally).
Interruptibility: synchronized cannot be interrupted; ReentrantLock supports lockInterruptibly().
Timeout acquisition: unavailable with synchronized, available via tryLock(timeout) in ReentrantLock.
Fairness: synchronized is non‑fair; ReentrantLock can be fair or non‑fair.
Condition variables: synchronized provides a single wait/notify pair; ReentrantLock offers multiple Condition objects.
Implementation: synchronized is handled by the JVM; ReentrantLock is built on AQS Java code.
7. What are the seven parameters of ThreadPoolExecutor and its execution flow?
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)Execution flow:
New task submitted
│
├─ if current threads < corePoolSize → create new thread
│
├─ else try to enqueue task
│ ├─ success → wait for a free thread
│ └─ failure → if threads < maximumPoolSize → create new thread
│ else → apply rejection policy (Abort, CallerRuns, Discard, DiscardOldest)Note: using newFixedThreadPool with an unbounded queue can cause OOM; newCachedThreadPool may create too many threads (max = Integer.MAX_VALUE). Manual ThreadPoolExecutor construction is recommended.
8. How does ThreadLocal work and why can it leak memory?
Each thread holds a ThreadLocalMap where the key is a weak reference to the ThreadLocal object and the value is a strong reference to the stored data.
When the ThreadLocal key is garbage‑collected, the map entry’s key becomes null but the value remains, preventing reclamation.
public void process() {
try {
threadLocal.set(value);
// business logic ...
} finally {
threadLocal.remove(); // must clean up
}
}9. Differences between CountDownLatch and CyclicBarrier
Purpose : Latch waits for a set of tasks to finish; Barrier waits for a group of threads to reach a common point.
Count direction : Latch counts down; Barrier counts up.
Reusability : Latch is one‑time use; Barrier can be reset and reused.
Exception handling : Latch tolerates partial thread failures; Barrier is broken by any thread exception.
// CountDownLatch example
CountDownLatch latch = new CountDownLatch(5);
for (int i = 0; i < 5; i++) {
executor.submit(() -> {
// task
latch.countDown();
});
}
latch.await(); // wait for 5 tasks
// CyclicBarrier example
CyclicBarrier barrier = new CyclicBarrier(5, () -> {
// callback after all arrive
});10. What are the four necessary conditions for deadlock?
Mutual exclusion : a resource can be held by only one thread.
Hold and wait : a thread holding one resource waits for another.
No preemption : held resources cannot be forcibly taken.
Circular wait : threads form a cycle of waiting.
public void transfer(Account from, Account to, int amount) {
synchronized (from) {
synchronized (to) { // opposite lock order can deadlock
from.balance -= amount;
to.balance += amount;
}
}
}
// Solution: acquire locks in a fixed global orderDeadlock detection can be done with jstack <PID> or VisualVM. Prevention strategies include fixed lock ordering, timeout mechanisms, and using tryLock.
I'm 老 J, see you in the next JVM‑focused article covering memory models, GC algorithms, class loading, and OOM troubleshooting.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Coder Trainee
Experienced in Java and Python, we share and learn together. For submissions or collaborations, DM us.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
