In Java's multithreading environment, managing access to shared resources is vital to prevent data inconsistency and race conditions. Locks and reentrant locks are essential tools to achieve this synchronization. Let's break these concepts into digestible parts to see how they work.
A lock is an object that allows threads to control access to shared resources. In Java, the java.util.concurrent.locks.Lock
interface provides more extensive locking operations than the traditional synchronized method or block. The primary advantage of locks is that they offer greater flexibility and control when dealing with thread synchronization.
Here’s a simple example to illustrate the use of a lock:
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class SimpleLockExample { private static final Lock lock = new ReentrantLock(); private static int counter = 0; public static void main(String[] args) { Thread thread1 = new Thread(SimpleLockExample::incrementCounter); Thread thread2 = new Thread(SimpleLockExample::incrementCounter); thread1.start(); thread2.start(); } public static void incrementCounter() { lock.lock(); // Acquire the lock try { for (int i = 0; i < 1000; i++) { counter++; // Critical section } } finally { lock.unlock(); // Ensure that the lock is released } } }
ReentrantLock
.counter
), we call lock.lock()
to acquire the lock.finally
: The finally
block ensures that the lock is released even if an exception occurs in the critical section.A reentrant lock is a special kind of lock that allows a thread to enter a lock that it already holds. This is crucial in cases where a method needs to call itself or when a method is called from another synchronized method. The ReentrantLock
class implements the Lock
interface and provides more features such as try-lock and timed lock.
Let's see how reentrant locks work:
import java.util.concurrent.locks.ReentrantLock; public class ReentrantLockExample { private final ReentrantLock reentrantLock = new ReentrantLock(); public void firstMethod() { reentrantLock.lock(); // Acquire the lock try { System.out.println("In the first method."); secondMethod(); // Calling another method that acquires the same lock } finally { reentrantLock.unlock(); // Unlock } } public void secondMethod() { reentrantLock.lock(); // Re-entering the lock try { System.out.println("In the second method."); } finally { reentrantLock.unlock(); // Unlock } } public static void main(String[] args) { ReentrantLockExample example = new ReentrantLockExample(); example.firstMethod(); } }
firstMethod()
acquires the lock, then calls secondMethod()
, which also attempts to acquire the same lock.Flexibility: Unlike synchronized blocks, reentrant locks provide more extensive methods for locking, such as tryLock()
which attempts to acquire the lock without blocking indefinitely.
Interruptible Locks: You can create interruptible locks by utilizing the lock's methods, allowing a thread to be interrupted while waiting for a lock.
Fairness Policy: Reentrant locks can be configured to be fair (i.e., service the longest-waiting thread first) by using a constructor parameter, which isn’t possible with standard synchronized objects.
import java.util.concurrent.locks.ReentrantLock; public class FairLockExample { private static final ReentrantLock fairLock = new ReentrantLock(true); // Fair lock public static void main(String[] args) { Thread threadA = new Thread(FairLockExample::lockedMethod); Thread threadB = new Thread(FairLockExample::lockedMethod); threadA.start(); threadB.start(); } public static void lockedMethod() { fairLock.lock(); try { System.out.println(Thread.currentThread().getName() + " acquired the lock."); } finally { fairLock.unlock(); } } }
In the above example, the fairLock
ensures that threads are granted access to the lock in the order they requested it, promoting fairness in thread scheduling.
By utilizing locks and reentrant locks effectively, you can manage resource access in concurrent programming, ensuring robust and error-free applications that scale well with multi-threaded environments.
16/10/2024 | Java
16/10/2024 | Java
30/10/2024 | Java
24/09/2024 | Java
11/12/2024 | Java
16/10/2024 | Java
23/09/2024 | Java
16/10/2024 | Java
23/09/2024 | Java
24/09/2024 | Java
24/09/2024 | Java
23/09/2024 | Java