java.util.concurrent.locks
package.
synchronized
block but with additional features.
synchronized
keyword, such as tryLock() with timeout, interruptible locks, and multiple condition variables.
tryLock()
, threads can attempt to acquire a lock without waiting indefinitely.
synchronized
, allows multiple Condition
objects for finer-grained signaling between threads.
synchronized
.
synchronized
.
ReentrantLock
Class:Method | Description |
---|---|
lock() |
Acquires the lock. If the lock is not available, the thread waits indefinitely until it is free. |
unlock() |
Releases the lock held by the current thread. Must be called in a finally block to avoid deadlocks. |
tryLock() |
Tries to acquire the lock immediately. Returns true if successful, otherwise false . Useful to avoid blocking a thread. |
tryLock(long timeout, TimeUnit unit) |
Tries to acquire the lock within the given timeout. Returns true if successful, otherwise false . Helps avoid deadlocks. |
lockInterruptibly() |
Acquires the lock unless the thread is interrupted while waiting. Allows a thread to respond to interrupts. |
isLocked() |
Returns true if the lock is held by any thread. |
isHeldByCurrentThread() |
Returns true if the current thread holds the lock. |
getHoldCount() |
Returns the number of times the current thread has acquired the lock. |
lock()
, unlock()
, isLocked()
, isHeldByCurrentThread()
and getHoldCount()
methods:
import java.util.concurrent.locks.ReentrantLock;
class SimpleLockDemo
{
private final ReentrantLock lock = new ReentrantLock();
public void doWork()
{
lock.lock(); // Acquire the lock
try
{
System.out.println(Thread.currentThread().getName() + " acquired the lock.");
System.out.println("Is lock held by any thread? " + lock.isLocked());
System.out.println("Is lock held by current thread? " + lock.isHeldByCurrentThread());
System.out.println("Hold count: " + lock.getHoldCount());
// Simulate some work
Thread.sleep(1000);
}
catch (InterruptedException e)
{
System.out.println(Thread.currentThread().getName() + " was interrupted.");
}
finally
{
lock.unlock(); // Release the lock
System.out.println(Thread.currentThread().getName() + " released the lock.");
}
}
}
// Thread subclass for using the lock
class WorkThread extends Thread
{
SimpleLockDemo demo;
public WorkThread(SimpleLockDemo demo, String name)
{
super(name);
this.demo = demo;
}
@Override
public void run()
{
demo.doWork();
}
}
public class MainApp4
{
public static void main(String[] args)
{
SimpleLockDemo demo = new SimpleLockDemo();
WorkThread t1 = new WorkThread(demo, "Thread-1");
WorkThread t2 = new WorkThread(demo, "Thread-2");
t1.start();
t2.start();
}
}
Thread-1 acquired the lock. Is lock held by any thread? true Is lock held by current thread? true Hold count: 1 Thread-2 acquired the lock. Thread-1 released the lock. Is lock held by any thread? true Is lock held by current thread? true Hold count: 1 Thread-2 released the lock.
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.TimeUnit;
class Resource
{
// any custom code
}
class MyThread1 extends Thread
{
private final ReentrantLock lock1;
private final ReentrantLock lock2;
MyThread1(ReentrantLock lock1, ReentrantLock lock2)
{
this.lock1 = lock1;
this.lock2 = lock2;
}
@Override
public void run()
{
try
{
if (lock1.tryLock(1, TimeUnit.SECONDS)) // Try to acquire lock1
{
System.out.println("Thread 1 has locked Resource 1");
Thread.sleep(500); // Simulate some work
if (lock2.tryLock(1, TimeUnit.SECONDS)) // Try to acquire lock2
{
try
{
System.out.println("Thread 1 has locked Resource 2");
}
finally
{
lock2.unlock();
System.out.println("Thread 1 released Resource 2");
}
}
else
{
System.out.println("Thread 1 could not acquire Resource 2, avoiding deadlock!");
}
lock1.unlock();
System.out.println("Thread 1 released Resource 1");
}
else
{
System.out.println("Thread 1 could not acquire Resource 1, skipping work!");
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
class MyThread2 extends Thread
{
private final ReentrantLock lock1;
private final ReentrantLock lock2;
MyThread2(ReentrantLock lock1, ReentrantLock lock2)
{
this.lock1 = lock1;
this.lock2 = lock2;
}
@Override
public void run()
{
try
{
if (lock2.tryLock(1, TimeUnit.SECONDS)) // Try to acquire lock2 first
{
System.out.println("Thread 2 has locked Resource 2");
Thread.sleep(500);
if (lock1.tryLock(1, TimeUnit.SECONDS)) // Try to acquire lock1
{
try
{
System.out.println("Thread 2 has locked Resource 1");
}
finally
{
lock1.unlock();
System.out.println("Thread 2 released Resource 1");
}
}
else
{
System.out.println("Thread 2 could not acquire Resource 1, avoiding deadlock!");
}
lock2.unlock();
System.out.println("Thread 2 released Resource 2");
}
else
{
System.out.println("Thread 2 could not acquire Resource 2, skipping work!");
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
public class DeadlockProblemSolved
{
public static void main(String[] args)
{
ReentrantLock lock1 = new ReentrantLock();
ReentrantLock lock2 = new ReentrantLock();
MyThread1 t1 = new MyThread1(lock1, lock2);
MyThread2 t2 = new MyThread2(lock1, lock2);
t1.start();
t2.start();
}
}
Thread 1 has locked Resource 1 Thread 2 has locked Resource 2 Thread 1 could not acquire Resource 2, avoiding deadlock! Thread 1 released Resource 1 Thread 2 could not acquire Resource 1, avoiding deadlock! Thread 2 released Resource 2
Your feedback helps us grow! If there's anything we can fix or improve, please let us know.
We’re here to make our tutorials better based on your thoughts and suggestions.