If synchronized is the syntax, the monitor is the underlying coordination mechanism.

You do not need JVM implementation internals to use Java concurrency well. But you do need a correct conceptual model of what the monitor is doing for you.


Problem Statement

When you write:

synchronized (lock) {
    // critical section
}

What actually happens conceptually?

If you cannot answer that, it becomes harder to reason about:

  • lock ownership
  • waiting threads
  • wait and notify
  • contention

That is why the monitor concept matters.


Correct Mental Model

In Java, every object can act as a monitor.

A monitor conceptually provides:

  • exclusive ownership by one thread at a time
  • a place where other threads wait to enter
  • a condition-waiting mechanism used by wait, notify, and notifyAll

When a thread enters a synchronized section on an object:

  • it tries to acquire that object’s monitor

When it exits:

  • it releases the monitor

This is why synchronized is often called intrinsic locking: the lock is built into the object model conceptually.


Why This Matters

If multiple threads synchronize on the same object, they coordinate through the same monitor.

If they synchronize on different objects, they do not.

That sounds obvious, but it explains many real bugs:

  • writer synchronizes on one lock
  • reader synchronizes on another
  • both assume the state is protected
  • it is not

The monitor model helps you see why.


Runnable Example

import java.util.concurrent.TimeUnit;

public class MonitorDemo {

    private static final Object LOCK = new Object();

    public static void main(String[] args) throws Exception {
        Thread first = new Thread(() -> runTask("first"), "first-thread");
        Thread second = new Thread(() -> runTask("second"), "second-thread");

        first.start();
        second.start();

        first.join();
        second.join();
    }

    static void runTask(String name) {
        synchronized (LOCK) {
            System.out.println(name + " entered critical section on " + Thread.currentThread().getName());
            sleep(800);
            System.out.println(name + " leaving critical section on " + Thread.currentThread().getName());
        }
    }

    static void sleep(long millis) {
        try {
            TimeUnit.MILLISECONDS.sleep(millis);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException(e);
        }
    }
}

What this shows:

  • both threads target the same monitor object
  • one thread owns the monitor at a time
  • the other must wait

That is the monitor doing its job.


Intrinsic Locking vs Explicit Locking

Intrinsic locking means:

  • monitor ownership is tied to the object used in synchronized

Explicit locking means:

  • a lock object such as ReentrantLock manages the ownership explicitly through APIs

For now, the important part is: monitor-based locking is the default built-in coordination model of Java objects.

Later posts compare it with explicit locks.


Production-Style Example

Suppose an in-memory inventory object protects these fields:

  • available
  • reserved
  • sold

If every update synchronizes on the same Inventory instance or same dedicated lock object, one monitor governs the invariant.

If one code path synchronizes on this and another on a separate lock field, protection is fractured.

That means:

  • the code may look “locked”
  • but the state is still effectively unprotected

The monitor model reveals why.


wait and notify Depend on Monitor Ownership

wait, notify, and notifyAll operate on the monitor too.

That is why Java requires them to be called only while holding the relevant monitor.

This later becomes critical when we discuss:

  • guarded blocks
  • producer-consumer designs
  • missed notifications

Without the monitor concept, those APIs feel arbitrary. With it, the rules are coherent.


Failure Modes

Common mistakes:

  • synchronizing on public objects that outside code may also lock
  • using different monitor objects for related shared state
  • calling wait/notify without really understanding the monitor involved

If a design cannot clearly state “this monitor protects this state,” it is too vague.


Testing and Debugging Notes

Review questions:

  1. what object is the monitor?
  2. which state does that monitor protect?
  3. do all relevant code paths use the same monitor?

These questions are simple, but they expose many locking flaws.

Thread dumps also become easier to read once you understand that BLOCKED often means a thread is waiting to enter a monitor owned elsewhere.


Decision Guide

Use one monitor per protected invariant boundary.

Do not rely on broad accidental locking. Make the protected state and its monitor relationship obvious.

That clarity matters more than cleverness.


Key Takeaways

  • a monitor is the conceptual synchronization mechanism behind synchronized
  • one thread owns a monitor at a time
  • wait, notify, and notifyAll depend on monitor ownership
  • monitor clarity is essential for correct intrinsic locking design

Next Post

Object Header Monitor Ownership and Monitor Entry in Java