Understanding Java Monitors: How Thread Synchronization Works
Java monitors provide a mechanism for thread synchronization by associating each object with a monitor lock, comprising an entry list, owner thread, and wait set, and the article explains their structure, thread state transitions, and demonstrates usage with a practical code example.
What is a Monitor?
In Java, a monitor is a mechanism used to implement thread synchronization. Every Java object has an associated monitor, and threads acquire and release it using the synchronized keyword, ensuring that only one thread can execute a synchronized block or method at a time.
Components of a Monitor
A monitor typically consists of three key parts:
Entry List : the set of threads waiting to acquire the monitor lock.
Owner Thread : the thread that currently holds the monitor lock.
Wait Set : the set of threads that have called wait() and are waiting to be notified.
Where Threads Wait
Entry List : Threads that attempt to enter a synchronized block or method but cannot obtain the monitor lock are placed here and remain blocked.
Wait Set : Threads that invoke wait() release the monitor lock and enter this set, staying waiting until another thread calls notify() or notifyAll() .
Thread State Transition Diagram
The following outlines the transitions between thread states:
New : Thread is created but not yet started.
Runnable : Thread has started and may be running.
Blocked : Thread is in the entry list, waiting for the monitor lock.
Waiting : Thread is in the wait set, awaiting notification via notify() or notifyAll() .
Timed Waiting : Thread is in the wait set with a timeout.
Terminated : Thread has completed execution.
Example Code Explanation
The example below demonstrates how threads move between these states using a shared lock object.
<code>public class MonitorExample {
private static final Object lock = new Object();
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
synchronized (lock) {
try {
System.out.println("Thread 1: Acquired lock, entering wait state.");
lock.wait();
System.out.println("Thread 1: Woken up, reacquired lock.");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
Thread thread2 = new Thread(() -> {
synchronized (lock) {
System.out.println("Thread 2: Acquired lock, notifying.");
lock.notify();
System.out.println("Thread 2: Notified, releasing lock.");
}
});
thread1.start();
try {
Thread.sleep(100); // Ensure thread1 starts first and enters wait state
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
thread2.start();
}
}
</code>Process Explanation
Thread 1 acquires the monitor lock : Enters the synchronized block and obtains the lock.
Calls lock.wait() : Releases the monitor lock and moves to the wait set.
Thread 2 acquires the monitor lock : Enters its synchronized block while Thread 1 is waiting.
Calls lock.notify() : Wakes up one thread in the wait set (Thread 1).
Thread 2 exits the synchronized block, releasing the monitor lock.
Thread 1 re-acquires the monitor lock : After being notified, it competes for the lock, regains it, and continues execution after wait() returns.
Summary
Monitor : Used for thread synchronization; each Java object has one.
Entry List : Threads waiting to acquire the monitor lock.
Wait Set : Threads that have called wait() and are waiting to be notified.
State Transitions : Threads move among New, Runnable, Blocked, Waiting, Timed Waiting, and Terminated states.
Java Captain
Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.
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.