One synchronization boundary
State and lock policy stay together instead of leaking into callers.
The Monitor Object pattern wraps state and synchronization together. Instead of spreading lock behavior across many callers, the object itself controls access through synchronized operations or equivalent coordination. This keeps invariants closer to the data they protect.
If an order queue, stock counter, or payment attempt registry is shared across multiple threads, the team needs one place that defines the legal coordination behavior. Scattered external locking makes that behavior fragile and easy to misuse.
A monitor object combines data, operations, and synchronization policy into one owned component. Callers do not decide independently how and when to lock. They use the object's protected methods. This reduces coordination drift and keeps invariants local to the state they matter to.
The pattern works best when there is a clear, finite set of operations over shared state. It works less well when lock scope becomes broad or when contention is so high that serialization destroys throughput.
State and lock policy stay together instead of leaking into callers.
The object can enforce meaningful rules while holding the right coordination context.
Simple safety sometimes costs throughput if too much work happens inside the monitor.
Keep the protected work narrow and close to the shared state.
Monitors work well when the state has a stable, meaningful interface.
Holding locks across IO or expensive computation can destroy throughput and liveness.
Multiple monitors with inconsistent lock ordering create deadlock risk.
package org.javaomnibus.inventory;
public final class InventoryMonitor {
private int available;
public InventoryMonitor(int available) {
this.available = available;
}
public synchronized boolean reserve(int quantity) {
if (quantity <= 0 || available < quantity) {
return false;
}
available -= quantity;
return true;
}
public synchronized int available() {
return available;
}
}