Интерфейс Lock
Интерфейс Lock из пакета java.util.concurrent.locks
предоставляет более гибкий механизм синхронизации потоков,
чем ключевое слово synchronized. Основное отличие
заключается в том, что блокировку можно захватить и освободить
в разных местах программы, а также использовать
дополнительные методы для проверки состояния блокировки.
В отличие от synchronized, который автоматически
освобождает монитор при выходе из блока, Lock требует
явного вызова метода unlock. Интерфейс Lock
реализуется классом ReentrantLock, который мы
и будем использовать в примерах.
Синтаксис
Lock lock = new ReentrantLock();
lock.lock();
try
{
// critical section
}
finally
{
lock.unlock();
}
Пример
Давайте рассмотрим простой пример использования Lock
для защиты критической секции от одновременного доступа
из нескольких потоков:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Main
{
private static int counter = 0;
private static final Lock lock = new ReentrantLock();
public static void main(String[] args) throws InterruptedException
{
Thread t1 = new Thread(() -> increment());
Thread t2 = new Thread(() -> increment());
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(counter);
}
private static void increment()
{
for (int i = 0; i < 1000; i++)
{
lock.lock();
try
{
counter++;
}
finally
{
lock.unlock();
}
}
}
}
Результат выполнения кода:
2000
Пример
Давайте используем метод tryLock, который пытается
захватить блокировку и возвращает true или false
в зависимости от результата, не блокируя поток навсегда:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Main
{
private static final Lock lock = new ReentrantLock();
public static void main(String[] args) throws InterruptedException
{
Thread t1 = new Thread(() -> tryIncrement());
t1.start();
lock.lock();
try
{
System.out.println("Main thread holds the lock");
Thread.sleep(1000);
}
finally
{
lock.unlock();
}
t1.join();
}
private static void tryIncrement()
{
if (lock.tryLock())
{
try
{
System.out.println("Lock acquired");
}
finally
{
lock.unlock();
}
}
else
{
System.out.println("Lock not available");
}
}
}
Результат выполнения кода:
Main thread holds the lock
Lock not available
Смотрите также
-
класс
ReentrantLock,
который является основной реализацией интерфейса Lock -
метод
lock,
который захватывает блокировку -
метод
unlock,
который освобождает блокировку -
ключевое слово
synchronized,
которое является встроенным механизмом синхронизации