Java : Lock with Examples

Lock (Java SE 19 & JDK 19) API Examples.
You will find code examples on most Lock methods.


Summary

Lock implementations provide more extensive locking operations than can be obtained using synchronized methods and statements. They allow more flexible structuring, may have quite different properties, and may support multiple associated Condition objects.

Class diagram

try (final var executor = Executors.newFixedThreadPool(3)) {
    final Lock 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!)

Methods

void lock ()

Acquires the lock.

try (final var executor = Executors.newFixedThreadPool(3)) {
    final Lock 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!)

void lockInterruptibly ()

Acquires the lock unless the current thread is interrupted.

try (final var executor = Executors.newFixedThreadPool(3)) {
    final Lock 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 Lock 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 ()

Returns a new Condition instance that is bound to this Lock instance.

final long current = System.nanoTime();
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;

try (var executor = Executors.newSingleThreadExecutor()) {
    final Lock 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.)

boolean tryLock ()

Acquires the lock only if it is free at the time of invocation.

final long current = System.nanoTime();
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;

try (var executor = Executors.newFixedThreadPool(2)) {
    final Lock 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 time, TimeUnit unit)

Acquires the lock if it is free within the given waiting time and the current thread has not been interrupted.

final long current = System.nanoTime();
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;

try (var executor = Executors.newFixedThreadPool(2)) {
    final Lock 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 ()

Releases the lock.

Please see lock().


Related posts

To top of page