Reentrant Lock in Java
The Lock interface is implemented by the ReentrantLock class, which also provides methods for synchronising access to shared resources. The code that controls the resource has calls to the lock and unlock functions all over it. This gives the active thread a lock on the resource and prohibits any other threads from attempting to do so.
ReentrantLock, as its name suggests, enables multiple entries by a thread into the lock on a resource. When the thread initially enters the lock, a hold count is initiated at one. Each time a thread enters lock before being released, the count goes up by one. When the hold count reaches zero, the resource is released. The count drops by one for each unlocking request.
When a resource is unlocked, reentrant locks also include an option that guarantees that the lock will always allow access to the thread which is waiting. This option is set up by passing true to the function Object() in native code.
Synchronization vs Reentrant Lock:
The synchronised keyword is typically used in Java to create thread synchronisation. The synchronised keyword is rather rigorous in its application, despite the fact that it offers some basic synchronisation. For instance, a thread can only accept a lock once. Because synchronised blocks lack a waiting queue mechanism, any thread can take the lock once a thread exits. This could cause some other thread to run out of resources for a very long time.
Java has reentrant locks to offer synchronisation with more flexibility.
- Fairness is another important distinction between ReentrantLock and the synchronised keyword. The term "synchronised" opposes fairness. No preference may be provided, and once the lock is released it can be acquired by any thread. ReentrantLock can be made fair by supplying the fairness property when creating an instance of the lock. If there is a dispute, the fairness property grants a lock to the thread that has been waiting for the longest.
- TryLock() method is the second distinction between synchronised and reentrant locks. A handy tryLock() function is provided by ReentrantLock, which only gets lock if it is available and not being held by another thread. This lessens the blocking caused by threads waiting for Java apps to lock in.
- Another distinction between ReentrantLock and Java's synchronised keyword is the latter's ability to stop threads while they are waiting for locks. There was no way to prevent a thread from becoming stuck waiting for a lock in the case of a synchronised keyword for an endless amount of time. When a thread is waiting for a lock, ReentrantLock's lockInterruptibly() function allows for interruption. If the lock is unavailable for a predetermined amount of time, tryLock() with timeout can be used to time out.
Thus, it is clear that there are several major distinctions between Java's ReentrantLock and the synchronised keyword. In summary, the Lock interface offers a great deal of flexibility and power and gives users considerable control over the lock acquisition process. This feature may be used to create extremely scalable Java applications.
The following are some significant Java Lock API interfaces and classes:
- Lock: This is the Lock API's fundamental interface. It offers all the benefits of a synchronised keyword along with extra options to define unique locking conditions and a timeout functionality for threads to wait for a lock. A few crucial methods are lock(), which acquires the lock, unlock(), tryLock(), which waits for the lock for a predetermined amount of time, and newCondition(), which creates the condition, among others.
- Condition: Condition objects have the added capability of creating several sets of wait, comparable to the Object wait-notify model. Lock objects always produce a Condition object. Await(), which is comparable to wait() and signal(), signalAll(), which is comparable to notify() and notifyAll() techniques, are a few of the crucial methods.
- ReadWriteLock: One lock is for read-only activities, and the other is for writing. This lock is known as the ReadWriteLock. As long as there are no writer threads, several reader threads may hold the read lock concurrently. There is an exclusive write lock.
- ReentrantLock: The Lock interface's most popular implementation class. The Lock interface is implemented by this class in a manner comparable to the synchronised keyword. ReentrantLock has several utility methods to access the threads holding the lock, threads waiting to acquire the lock, etc. in addition to implementing the Lock interface. Because synchronised blocks must have the lock on the same monitor object in order to function, a thread can enter a synchronised block if it has the monitor object lock and another synchronised block needs it. ReentrantLock, I believe, is the name of the class for this reason.
Program:
Import java.io.*;
Import java.util.*;
class ReentrantLock {
ReentrantLock lock = new ReentrantLock();
int c = 0;
int Count() {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + " Count: " + count);
return c++;
} finally {
lock.unlock();
}
}
int CountTwo() {
return c++;
}
public static void main(String args[]) {
ThreadTest cn = new ThreadTest();
Thread t3 = new Thread() {
public void run() {
while (cn.Count() < 6) {
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
ex.printStackTrace(); }
}
}
};
Thread t4 = new Thread() {
public void run() {
while (counter.getCount() < 4) {
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
t3.start();
t4.start();
}}
Output:
Thread-0 Count: 0
Thread-1 Count: 1
Thread-1 Count: 2
Thread-0 Count: 3