Monitors or ObjectMonitors are a multithreading construct, they rely on the OS’ mutex lock primitive and when created are a part of an object, used to track its ownership (Which thread has the object’s lock). Because of this they are also known as intrinsic locks.
Monitors are the core part of the system that controls thread ownership of objects with the synchronize keyword & Object Monitor Methods.
They are not Java Objects, instead, ObjectMonitors are native C++ structs and are allocated in a portion of the heap that is managed directly by the JVM.
They contain:
- Native OS Mutex (the lock)
- Pointer to the currently owning thread
- Entry Set - Set of threads that are blocked, waiting to acquire the lock
- Wait Set - Set of threads that called
wait()in asynchronizedblock and thus temporarily given up the lock - Displaced Header - metadata of the object (unless ObjectMonitorTable is enabled)
When is a Monitor Created?
1 Monitor always belongs to 1 object, but not all objects have monitors. Monitors are only created when threads are in contention for ownership over a single object.
As for why a Monitor isn’t needed when only a single thread is locking an object, see how the object header efficiently handles such cases.
Example of when a Monitor is created for an object
class Main {
public static void main(String[] args) {
ThreadSafeCounter counter = new ThreadSafeCounter();
// This thread calls this method on an instance of ThreadSafeCounter,
// No monitor is created, as only 1 thread is contending for the lock
new Thread(()-> counter.incr()).start();
// This thread then calls a method on the same instance,
// while the first thread is still running the incr() method.
// Now a Monitor is created as 2 threads are contending for ownership of the same object
new Thread(()-> counter.get()).start();
}
}
class ThreadSafeCounter {
private int count = 0;
public synchronized int get(){
return count;
}
public synchronized void incr() {
// artificially delay this method
try { Thread.sleep(1000); } catch(InterruptedException _e) {}
count++;
}
}