Java : ReentrantLock with Examples
ReentrantLock (Java SE 20 & JDK 20) API Examples.
You will find code examples on most ReentrantLock methods.
Summary
try (final var executor = Executors.newFixedThreadPool(3)) {
final var lock = new ReentrantLock();
for (int i = 1; i <= 3; i++) {
final var id = i;
TimeUnit.MILLISECONDS.sleep(100);
executor.submit(() -> {
System.out.println(id + " : lock ...");
lock.lock();
try {
System.out.println(id + " : lock OK!");
TimeUnit.SECONDS.sleep(2);
System.out.println(id + " : sleep completed (unlock!)");
} catch (InterruptedException e) {
System.out.println("InterruptedException!");
} finally {
lock.unlock();
}
});
}
}
// Result
// ↓
//1 : lock ...
//1 : lock OK!
//2 : lock ...
//3 : lock ...
//1 : sleep completed (unlock!)
//2 : lock OK!
//2 : sleep completed (unlock!)
//3 : lock OK!
//3 : sleep completed (unlock!)
Constructors
ReentrantLock ()
try (final var executor = Executors.newFixedThreadPool(3)) {
final var lock = new ReentrantLock();
for (int i = 1; i <= 3; i++) {
final var id = i;
TimeUnit.MILLISECONDS.sleep(100);
executor.submit(() -> {
System.out.println(id + " : lock ...");
lock.lock();
try {
System.out.println(id + " : lock OK!");
TimeUnit.SECONDS.sleep(2);
System.out.println(id + " : sleep completed (unlock!)");
} catch (InterruptedException e) {
System.out.println("InterruptedException!");
} finally {
lock.unlock();
}
});
}
}
// Result
// ↓
//1 : lock ...
//1 : lock OK!
//2 : lock ...
//3 : lock ...
//1 : sleep completed (unlock!)
//2 : lock OK!
//2 : sleep completed (unlock!)
//3 : lock OK!
//3 : sleep completed (unlock!)
ReentrantLock (boolean fair)
Please see also : ReentrantLock()
void testFair(boolean fair) throws InterruptedException {
final var lock = new ReentrantLock(fair);
System.out.println("isFair = " + lock.isFair());
final var order = new ArrayList<Integer>();
try (final var executor = Executors.newFixedThreadPool(2)) {
lock.lock();
try {
executor.submit(() -> {
try {
lock.lock();
order.add(1);
} finally {
lock.unlock();
}
try {
lock.lock();
order.add(2);
} finally {
lock.unlock();
}
});
TimeUnit.MILLISECONDS.sleep(100);
executor.submit(() -> {
try {
lock.lock();
order.add(3);
} finally {
lock.unlock();
}
});
TimeUnit.MILLISECONDS.sleep(100);
} finally {
lock.unlock();
}
}
System.out.println("order = " + order);
}
testFair(true);
// Result
// ↓
//isFair = true
//order = [1, 3, 2]
testFair(false);
// Result
// ↓
//isFair = false
//order = [1, 2, 3]
Methods
int getHoldCount ()
final var lock = new ReentrantLock();
System.out.println(lock.getHoldCount()); // 0
System.out.println(lock.isHeldByCurrentThread()); // false
lock.lock();
try {
System.out.println(lock.getHoldCount()); // 1
System.out.println(lock.isHeldByCurrentThread()); // true
lock.lock();
try {
System.out.println(lock.getHoldCount()); // 2
System.out.println(lock.isHeldByCurrentThread()); // true
lock.lock();
try {
System.out.println(lock.getHoldCount()); // 3
System.out.println(lock.isHeldByCurrentThread()); // true
} finally {
lock.unlock();
}
System.out.println(lock.getHoldCount()); // 2
System.out.println(lock.isHeldByCurrentThread()); // true
} finally {
lock.unlock();
}
System.out.println(lock.getHoldCount()); // 1
System.out.println(lock.isHeldByCurrentThread()); // true
} finally {
lock.unlock();
}
System.out.println(lock.getHoldCount()); // 0
System.out.println(lock.isHeldByCurrentThread()); // false
protected Thread getOwner ()
protected. I think it's rare to create a subclass of this class. Therefore, the code example is omitted.
protected Collection<Thread> getQueuedThreads ()
protected. I think it's rare to create a subclass of this class. Therefore, the code example is omitted.
final int getQueueLength ()
final var lock = new ReentrantLock();
try (final var executor = Executors.newFixedThreadPool(5)) {
for (int i = 1; i <= 5; i++) {
final var id = i;
TimeUnit.MILLISECONDS.sleep(100);
executor.submit(() -> {
System.out.printf("%d : lock ... : queue length = %d (%b)%n",
id, lock.getQueueLength(), lock.hasQueuedThreads());
lock.lock();
try {
System.out.printf("%d : lock OK! : queue length = %d (%b)%n",
id, lock.getQueueLength(), lock.hasQueuedThreads());
TimeUnit.SECONDS.sleep(3);
System.out.println(id + " : sleep completed (unlock!)");
} catch (InterruptedException e) {
System.out.println("InterruptedException!");
} finally {
lock.unlock();
}
});
}
}
// Result
// ↓
//1 : lock ... : queue length = 0 (false)
//1 : lock OK! : queue length = 0 (false)
//2 : lock ... : queue length = 0 (false)
//3 : lock ... : queue length = 1 (true)
//4 : lock ... : queue length = 2 (true)
//5 : lock ... : queue length = 3 (true)
//1 : sleep completed (unlock!)
//2 : lock OK! : queue length = 3 (true)
//2 : sleep completed (unlock!)
//3 : lock OK! : queue length = 2 (true)
//3 : sleep completed (unlock!)
//4 : lock OK! : queue length = 1 (true)
//4 : sleep completed (unlock!)
//5 : lock OK! : queue length = 0 (false)
//5 : sleep completed (unlock!)
protected Collection<Thread> getWaitingThreads (Condition condition)
protected. I think it's rare to create a subclass of this class. Therefore, the code example is omitted.
int getWaitQueueLength (Condition condition)
try (var executor = Executors.newFixedThreadPool(3)) {
final var lock = new ReentrantLock();
final var cond = lock.newCondition();
for (int i = 1; i <= 3; i++) {
final var id = i;
TimeUnit.MILLISECONDS.sleep(100);
executor.submit(() -> {
lock.lock();
try {
System.out.printf("%d : await ... : wait queue length = %d (%b)%n",
id, lock.getWaitQueueLength(cond), lock.hasWaiters(cond));
cond.await();
System.out.printf("%d : await OK! : wait queue length = %d (%b)%n",
id, lock.getWaitQueueLength(cond), lock.hasWaiters(cond));
} catch (InterruptedException e) {
System.out.println("InterruptedException!");
} finally {
lock.unlock();
}
});
}
TimeUnit.SECONDS.sleep(2);
for (int i = 0; i < 3; i++) {
lock.lock();
try {
System.out.println("signal!");
cond.signal();
} finally {
lock.unlock();
}
TimeUnit.SECONDS.sleep(1);
}
}
// Result
// ↓
//1 : await ... : wait queue length = 0 (false)
//2 : await ... : wait queue length = 1 (true)
//3 : await ... : wait queue length = 2 (true)
//signal!
//1 : await OK! : wait queue length = 2 (true)
//signal!
//2 : await OK! : wait queue length = 1 (true)
//signal!
//3 : await OK! : wait queue length = 0 (false)
final boolean hasQueuedThread (Thread thread)
try (var executor = Executors.newSingleThreadExecutor()) {
final var lock = new ReentrantLock();
final var main = Thread.currentThread();
executor.submit(() -> {
try {
lock.lock();
try {
System.out.println("A : lock OK!");
TimeUnit.SECONDS.sleep(1);
System.out.println("A : main is waiting = " + lock.hasQueuedThread(main));
TimeUnit.SECONDS.sleep(2);
System.out.println("A : main is waiting = " + lock.hasQueuedThread(main));
System.out.println("A : unlock!");
} finally {
lock.unlock();
}
TimeUnit.SECONDS.sleep(2);
System.out.println("A : main is waiting = " + lock.hasQueuedThread(main));
} catch (InterruptedException e) {
System.out.println("InterruptedException!");
}
});
TimeUnit.SECONDS.sleep(2);
System.out.println("main : lock ...");
lock.lock();
try {
System.out.println("main : lock OK!");
TimeUnit.SECONDS.sleep(1);
System.out.println("main : unlock!");
} finally {
lock.unlock();
}
}
// Result
// ↓
//A : lock OK!
//A : main is waiting = false
//main : lock ...
//A : main is waiting = true
//A : unlock!
//main : lock OK!
//main : unlock!
//A : main is waiting = false
final boolean hasQueuedThreads ()
Please see getQueueLength().
boolean hasWaiters (Condition condition)
Please see getWaitQueueLength(Condition condition).
final boolean isFair ()
Please see ReentrantLock(boolean fair).
boolean isHeldByCurrentThread ()
Please see getHoldCount().
boolean isLocked ()
final var lock = new ReentrantLock();
try (final var executor = Executors.newFixedThreadPool(3)) {
for (int i = 1; i <= 3; i++) {
final var id = i;
TimeUnit.MILLISECONDS.sleep(100);
executor.submit(() -> {
System.out.printf("%d : lock ... : isLocked = %b%n", id, lock.isLocked());
lock.lock();
try {
System.out.printf("%d : lock OK! : isLocked = %b%n", id, lock.isLocked());
TimeUnit.SECONDS.sleep(2);
System.out.printf("%d : sleep completed (unlock!)%n", id);
} catch (InterruptedException e) {
System.out.println("InterruptedException!");
} finally {
lock.unlock();
}
});
}
}
System.out.printf("main : isLocked = %b%n", lock.isLocked());
// Result
// ↓
//1 : lock ... : isLocked = false
//1 : lock OK! : isLocked = true
//2 : lock ... : isLocked = true
//3 : lock ... : isLocked = true
//1 : sleep completed (unlock!)
//2 : lock OK! : isLocked = true
//2 : sleep completed (unlock!)
//3 : lock OK! : isLocked = true
//3 : sleep completed (unlock!)
//main : isLocked = false
void lock ()
Please see ReentrantLock().
void lockInterruptibly ()
try (final var executor = Executors.newFixedThreadPool(3)) {
final var lock = new ReentrantLock();
for (int i = 1; i <= 3; i++) {
final var id = i;
TimeUnit.MILLISECONDS.sleep(100);
executor.submit(() -> {
try {
System.out.println(id + " : lock ...");
lock.lockInterruptibly();
try {
System.out.println(id + " : lock OK!");
TimeUnit.SECONDS.sleep(2);
System.out.println(id + " : sleep completed (unlock!)");
} finally {
lock.unlock();
}
} catch (InterruptedException e) {
System.out.println("InterruptedException!");
}
});
}
}
// Result
// ↓
//1 : lock ...
//1 : lock OK!
//2 : lock ...
//3 : lock ...
//1 : sleep completed (unlock!)
//2 : lock OK!
//2 : sleep completed (unlock!)
//3 : lock OK!
//3 : sleep completed (unlock!)
try (final var executor = Executors.newFixedThreadPool(2)) {
final var lock = new ReentrantLock();
class Task implements Runnable {
private final String name;
Task(String name) {
this.name = name;
}
@Override
public void run() {
try {
System.out.println(name + " : lock ...");
lock.lockInterruptibly();
try {
System.out.println(name + " : lock OK!");
TimeUnit.SECONDS.sleep(2);
System.out.println(name + " : sleep completed (unlock!)");
} finally {
lock.unlock();
}
} catch (InterruptedException e) {
System.out.println(name + " : InterruptedException!");
}
}
}
executor.submit(new Task("A"));
TimeUnit.MILLISECONDS.sleep(100);
final var futureB = executor.submit(new Task("B"));
TimeUnit.MILLISECONDS.sleep(100);
System.out.println("cancel task(B)");
futureB.cancel(true);
}
// Result
// ↓
//A : lock ...
//A : lock OK!
//B : lock ...
//cancel task(B)
//B : InterruptedException!
//A : sleep completed (unlock!)
Condition newCondition ()
final long current = System.nanoTime();
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;
try (var executor = Executors.newSingleThreadExecutor()) {
final var lock = new ReentrantLock();
final var cond = lock.newCondition();
executor.submit(() -> {
System.out.printf("lock ... (%f sec.)%n", elapsedTime.getAsDouble());
lock.lock();
try {
System.out.printf("await ... (%f sec.)%n", elapsedTime.getAsDouble());
cond.await();
System.out.printf("await OK! (%f sec.)%n", elapsedTime.getAsDouble());
} catch (InterruptedException e) {
System.out.println("InterruptedException!");
} finally {
lock.unlock();
}
});
TimeUnit.SECONDS.sleep(5);
lock.lock();
try {
System.out.printf("signal! (%f sec.)%n", elapsedTime.getAsDouble());
cond.signal();
} finally {
lock.unlock();
}
}
// Result
// ↓
//lock ... (0.003795 sec.)
//await ... (0.006260 sec.)
//signal! (5.019196 sec.)
//await OK! (5.019534 sec.)
String toString ()
final var lock = new ReentrantLock();
final var str1 = lock.toString();
// java.util.concurrent.locks.ReentrantLock@20bd8be5[Unlocked]
System.out.println(str1);
lock.lock();
try {
final var str2 = lock.toString();
// java.util.concurrent.locks.ReentrantLock@20bd8be5[Locked by thread Test worker]
System.out.println(str2);
} finally {
lock.unlock();
}
boolean tryLock ()
final long current = System.nanoTime();
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;
try (var executor = Executors.newFixedThreadPool(2)) {
final var lock = new ReentrantLock();
executor.submit(() -> {
lock.lock();
try {
System.out.println("A : lock OK!");
TimeUnit.SECONDS.sleep(5);
System.out.println("A : sleep completed (unlock!)");
} catch (InterruptedException e) {
System.out.println("InterruptedException!");
} finally {
lock.unlock();
}
});
TimeUnit.MILLISECONDS.sleep(100);
executor.submit(() -> {
try {
while (true) {
if (lock.tryLock()) {
try {
System.out.printf("B : tryLock = true (%f sec.)%n",
elapsedTime.getAsDouble());
break;
} finally {
lock.unlock();
}
}
System.out.printf("B : tryLock = false (%f sec.)%n",
elapsedTime.getAsDouble());
TimeUnit.SECONDS.sleep(2);
}
} catch (InterruptedException e) {
System.out.println("InterruptedException!");
}
});
}
// Result
// ↓
//A : lock OK!
//B : tryLock = false (0.113863 sec.)
//B : tryLock = false (2.125517 sec.)
//B : tryLock = false (4.135200 sec.)
//A : sleep completed (unlock!)
//B : tryLock = true (6.139156 sec.)
boolean tryLock (long timeout, TimeUnit unit)
final long current = System.nanoTime();
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;
try (var executor = Executors.newFixedThreadPool(2)) {
final var lock = new ReentrantLock();
executor.submit(() -> {
lock.lock();
try {
System.out.println("A : lock OK!");
TimeUnit.SECONDS.sleep(5);
System.out.println("A : sleep completed (unlock!)");
} catch (InterruptedException e) {
System.out.println("InterruptedException!");
} finally {
lock.unlock();
}
});
TimeUnit.MILLISECONDS.sleep(100);
executor.submit(() -> {
try {
while (true) {
if (lock.tryLock(2, TimeUnit.SECONDS)) {
try {
System.out.printf("B : tryLock = true (%f sec.)%n",
elapsedTime.getAsDouble());
break;
} finally {
lock.unlock();
}
}
System.out.printf("B : tryLock = false (%f sec.)%n",
elapsedTime.getAsDouble());
}
} catch (InterruptedException e) {
System.out.println("InterruptedException!");
}
});
}
// Result
// ↓
//A : lock OK!
//B : tryLock = false (2.114785 sec.)
//B : tryLock = false (4.131868 sec.)
//A : sleep completed (unlock!)
//B : tryLock = true (5.011976 sec.)
void unlock ()
Please see ReentrantLock().
Related posts
- API Examples
- BlockingQueue
- Callable
- CancellationException
- ConcurrentHashMap.KeySetView
- ConcurrentLinkedDeque
- ConcurrentLinkedQueue
- ConcurrentMap
- ConcurrentModificationException
- ConcurrentSkipListSet
- Condition
- CopyOnWriteArrayList
- CopyOnWriteArraySet
- CountDownLatch
- CyclicBarrier
- Exchanger
- Executor
- ExecutorService
- Executors
- Future
- Future.State
- FutureTask
- InterruptedException
- Lock
- Runnable
- Semaphore
- Thread
- ThreadGroup
- ThreadLocal
- TimeUnit