Thread Monitor Locks(Mutexes)
Table of Contents
How to Limit Access to Shared Resources #
In Java a way to limit access to shared resources is to use a monitor lock. Think of it as a physical lock on a door. Only one person can have the key to the lock at a time. This prevents multiple people from entering the room at the same time. In Java, this lock is called a monitor lock or a mutex.
What is a Monitor Lock #
A monitor lock (also known as an intrinsic lock or a mutex) is a mechanism used to provide synchronization between threads. It ensures that only one thread can execute a block of code protected by the lock at a time, thus preventing race conditions and ensuring thread safety when accessing shared resources.
How to Use Monitor Locks #
Every object in Java has an associated monitor lock.
Each object in Java has an associated monitor lock. When a thread wants to execute a synchronized method or block of code on an object, it must first acquire the object’s monitor lock. If the lock is already held by another thread, the requesting thread is blocked until the lock is released.
Monitor locks are implemented in Java using the synchronized keyword, which can be applied to methods or blocks of code that need to be protected from concurrent access by multiple threads. Example resources that need to be protected include shared data structures, files, and I/O streams.
Synchronized Methods #
You can use the synchronized keyword to make a method synchronized. This means that only one thread can execute the method at a time.
public class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
}
The monitor lock for the increment method is the Counter object itself. When a method is synchronized, the monitor lock is the object on which the method is called. This would be the this object in the example above.
Synchronized Blocks #
Use the synchronized keyword to create a synchronized block of code. This allows you to specify the object that will act as the monitor lock.
public class Counter {
private int count = 0;
private Object lock = new Object();
public void increment() {
synchronized (lock) {
count++;
}
}
}
In this example, the lock object is used as the monitor lock for the synchronized block. If the this object is used, the monitor lock would be the Counter object itself, similar to the synchronized method.
public void increment() {
synchronized (this) {
count++;
}
}
Reentrant Locks #
The java.util.concurrent.locks.ReentrantLock class provides a more flexible alternative to the synchronized keyword. It allows you to create lock objects that can be acquired and released in a more controlled manner. Reentrant locks also provide additional features such as timed waits which can be useful in certain situations.
public class Counter {
private int count = 0;
private ReentrantLock lock = new ReentranHitLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
}
You should always release the lock in a finally block to ensure that it is released even if an exception occurs within the synchronized block.