Thread starvation and deadlock are common concurrency issues that can severely impact application performance and responsiveness. Diagnosing these problems involves analyzing thread behavior, while resolving them requires careful synchronization design, proper resource management, and fair thread scheduling.
Key Points: • Thread dumps, VisualVM, JConsole, Java Mission Control, and jstack are commonly used to identify blocked, waiting, or deadlocked threads. • Deadlocks can be prevented by acquiring locks in a consistent order, minimizing nested locks, and using timeout-based locking. • Thread starvation can be reduced by using fair locks, balanced thread pools, and avoiding long-running tasks that monopolize resources.
Example: In a banking application, Thread A locks Account 1 and waits for Account 2, while Thread B locks Account 2 and waits for Account 1. Both threads wait indefinitely, causing a deadlock. Similarly, starvation can occur if high-priority tasks continuously occupy all worker threads, preventing other tasks from executing.
Code Example:
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public class DeadlockPrevention {
private final ReentrantLock lock1 =
new ReentrantLock(true);
private final ReentrantLock lock2 =
new ReentrantLock(true);
public void process()
throws InterruptedException {if (lock1.tryLock(
1,
TimeUnit.SECONDS)) {
try {if (lock2.tryLock(
1,
TimeUnit.SECONDS)) {
try {
System.out.println(
"Task Executed");
} finally {
lock2.unlock();
}
}
} finally {
lock1.unlock();
}
}
}
}Diagnosis Techniques: • Generate thread dumps using jstack or JVM monitoring tools. • Look for BLOCKED, WAITING, or TIMED_WAITING thread states. • Analyze deadlock reports included in thread dumps. • Monitor thread pool utilization and queue lengths. • Check lock contention metrics and thread execution times.
Interview Tip: A concise interview answer is: I diagnose deadlocks and thread starvation using thread dumps and monitoring tools such as VisualVM or jstack. To prevent deadlocks, I enforce a consistent lock acquisition order, minimize nested locking, and use tryLock with timeouts. To avoid starvation, I use fair locks, properly sized thread pools, and ensure that long-running tasks do not monopolize shared resources.