Synchronization is built around an internal object property known as:
- intrinsic lock
- monitor lock
- implicit lock
- or simply monitor.
Each object in Java is associated with a monitor, which a thread can lock or unlock.
- Only one thread at a time may hold a lock on a monitor.
- Any other threads attempting to lock that monitor are blocked until they can obtain a lock on that monitor.
Intrinsic locks play a role in both aspects of synchronization:
- enforcing exclusive access to an object's state
- and establishing happens-before relationships that are essential to visibility.
By convention, a thread that needs exclusive and consistent access to an object's fields has to acquire the object's intrinsic lock before accessing them, and then release the intrinsic lock when it's done with them.
All lock acquisition and release to occur in a block-structured way: when multiple locks are acquired they must be released:
- in the opposite order,
- in the same lexical scope in which they were acquired.
A thread is said to own the intrinsic lock between the time it has acquired the lock and released the lock.
As long as a thread owns an intrinsic lock, no other thread can acquire the same lock.
The other thread will block when it attempts to acquire the lock.
When a thread releases an intrinsic lock, a happens-before relationship is established between that action and any subsequent acquisition of the same lock.
A thread cannot acquire a lock owned by another thread but a thread can acquire a lock that it already owns. Allowing a thread to acquire the same lock more than once enables reentrant synchronization.
This kind of lock is easy to use, but has many limitations. More sophisticated locking idioms are supported by the java.util.concurrent.locks package. See Java Concurrency - Lock Objects (java.util.concurrent.locks)
Class level lock it the synchronized method is static
Object level lock it the synchronized method is instantiated (ie not static)