java.util.concurrent.Locks Расширенное руководство

1. Обзор

Короче говоря, замок является более гибким, чем стандартные блоки синхронизации, более сложный механизм синхронизации потоков.

Поскольку Java 1.5, Блокировка интерфейса всегда существовала. Он определен в java.util.concurrent.lock пакете, который обеспечивает большую операцию запирания.

В этой статье мы рассмотрим различные реализации интерфейса Лок и его применение.

2. Разница блокировки между блоком и Синхронным

Некоторые различия между использованием блоков синхронизации с LockLock API:

  • Синхронизировать блок целиком содержится в этом процессе - мы будем иметь блокировку API () и разблокировать () операцию в отдельном процессе
  • синхронизированный блок не поддерживает справедливость, любой поток может получить заблокирован после освобождения, не могут быть указаны предпочтения. Определяя справедливую собственность, мы можем добиться справедливости в API блокировки. Это гарантирует, что длинные нити ожидания могут получить доступ к замку
  • Если поток не может получить доступ к синхронизации блока, поток будет заблокирован. Указанный замок tryLock (API) при условии, методом. Только тогда, когда поток доступен и не имеет какой-либо другой поток, поток будет заблокирована. Это уменьшает поток ожидает в течение времени блокировки блокирующего
  • В состоянии «ожиданий» для потока, чтобы получить доступ к синхронизации блока не может быть прервано. Указанный замок lockInterruptibly API обеспечивает способ (), который может быть использован, чтобы прервать поток, который ожидает блокировки

3. Блокировка API

Давайте посмотрим на метод блокировки:

  • аннулируется замок () - получает блокировку (если таковой имеется); Если блокировка отсутствует, то поток будет заблокирован до тех пор, пока блокировка не будет отпущена
  • аннулированию lockInterruptibly () - Это похоже на блокировку (), но он позволяет блокированный поток прерывается и выполняется метание восстановления java.lang.InterruptedException
  • булево tryLock () - это блокировка () неблокирующая версию метода, он будет пытаться немедленно получить блокировку и возвращает истину, если блокировка прошла успешно
  • булево tryLock (длинный тайм-аут, TimeUnit TimeUnit) - Это похоже на tryLock (), за исключением того, что отказаться, прежде чем пытаться получить Блокировка ожидания тайм-аут дал
  • недействительным разблокировать) (- экземпляр разблокировки замка

Вы всегда должны разблокировать заблокированный экземпляр, чтобы избежать тупиковых ситуаций. Рекомендуемое применение блокировки блок должен содержать TRY / поймать и, наконец, блоки:

Lock lock = ...; 
lock.lock();
try {
    // access to the shared resource
} finally {
    lock.unlock();
}

Кроме того, чтобы заблокировать интерфейс, у нас есть интерфейс ReadWriteLock, который поддерживает блокировку, один только для чтения операций и один для записи. До тех пор пока не писать, читать замок может поддерживаться одновременно несколькими потоками.

ReadWriteLock способ приобретения декларирование чтения или записи блокировки:

  • Блокировка (блокировка чтения) - возвращает блокировку для чтения
  • Блокировка (блокировка записи) - Возвращает блокировку для записи

4. Блокировка достижения

4,1 ReentrantLock

ReentrantLock класс реализует интерфейс Lock. Это обеспечивает ту же семантику параллелизма и память, например, с использованием методы синхронного доступа и неявной блокировки монитора заявления, с расширенной функциональностью.

Давайте посмотрим, как мы можем использовать ReenrtantLock синхронизации:

public class SharedObject {
    //...
    ReentrantLock lock = new ReentrantLock();
    int counter = 0;
 
    public void perform() {
        lock.lock();
        try {
            // Critical section here
            count++;
        } finally {
            lock.unlock();
        }
    }
    //...
}

Мы должны убедиться, что примерочные, наконец, блок блокировки пакетов () и разблокировать () вызов, чтобы избежать тупиковых ситуаций.

Давайте посмотрим на tryLock () работает:

public void performTryLock(){
    //...
    boolean isLockAcquired = lock.tryLock(1, TimeUnit.SECONDS);
     
    if(isLockAcquired) {
        try {
            //Critical section here
        } finally {
            lock.unlock();
        }
    }
    //...
}

В этом случае вызов tryLock () поток будет ждать в течение секунды, и если блокировка не доступна, то отказаться ждать.

4,2 ReentrantReadWriteLock

ReentrantReadWriteLock ReadWriteLock класс реализует интерфейс.

Давайте посмотрим на правила или блокировкой чтения поток получает блокировку записи из:

Read Lock - Если ни один из потоков не запертые или написать запрос , он несколько потоков могут получить блокировку чтения
блокировки записи - если нет тпотоков чтения или записи, только один поток может получить блокировку записи
Давайте посмотрим на то, как вы можете использовать ReadWriteLock:

public class SynchronizedHashMapWithReadWriteLock {
 
    Map<String,String> syncHashMap = new HashMap<>();
    ReadWriteLock lock = new ReentrantReadWriteLock();
    // ...
    Lock writeLock = lock.writeLock();
 
    public void put(String key, String value) {
        try {
            writeLock.lock();
            syncHashMap.put(key, value);
        } finally {
            writeLock.unlock();
        }
    }
    ...
    public String remove(String key){
        try {
            writeLock.lock();
            return syncHashMap.remove(key);
        } finally {
            writeLock.unlock();
        }
    }
    //...
}

Для обоих написания метода, мы должны использовать блокировку записи, чтобы окружить критическую область, только один поток может получить доступ к нему:

Lock readLock = lock.readLock();
//...
public String get(String key){
    try {
        readLock.lock();
        return syncHashMap.get(key);
    } finally {
        readLock.unlock();
    }
}
 
public boolean containsKey(String key) {
    try {
        readLock.lock();
        return syncHashMap.containsKey(key);
    } finally {
        readLock.unlock();
    }
}

Для оба чтения методы необходимо использовать блокировку чтения, чтобы окружать критическую секцию. Если ни одна операция записи не выполняется, несколько потоков могут получить доступ в этот раздел.

4,3 StampedLock

StampedLock введена в Java 8. Он также поддерживает блокировку чтения-записи. Тем не менее, метод сбора блокировки возвращает чек на снятие блокировки или блокировки остается в силе штамп:

public class StampedLockDemo {
    Map<String,String> map = new HashMap<>();
    private StampedLock lock = new StampedLock();
 
    public void put(String key, String value){
        long stamp = lock.writeLock();
        try {
            map.put(key, value);
        } finally {
            lock.unlockWrite(stamp);
        }
    }
 
    public String get(String key) throws InterruptedException {
        long stamp = lock.readLock();
        try {
            return map.get(key);
        } finally {
            lock.unlockRead(stamp);
        }
    }
}

Другая функция заключается в обеспечение StampedLock оптимистической блокировки. Большую часть времени, операции чтения не нужно ждать, пока операция записи, чтобы закончить, так что не полномасштабная читать замок.

Вместо этого мы можем обновить блокировку следующим образом:

public String readWithOptimisticLock(String key) {
    long stamp = lock.tryOptimisticRead();
    String value = map.get(key);
 
    if(!lock.validate(stamp)) {
        stamp = lock.readLock();
        try {
            return map.get(key);
        } finally {
            lock.unlock(stamp);               
        }
    }
    return value;
}

5. условия

Класс условия обеспечивает поточно ожидание некоторой способность реализовать ключевые элементы ситуации.

Когда поток, чтобы получить доступ к критической области, но не выполнил необходимые условия для его работы, такая ситуация может возникнуть. Например, читатели могут получить доступ к общей очереди блокировки поток, очередь еще не имеет каких-либо данных, которые будут потребляться.

Традиционно, Java предоставляет нить ожидания для обмена (), Notify () и метод notifyAll (). Условия подобный механизм, но кроме того, мы можем указать несколько критериев:

public class ReentrantLockWithCondition {
 
    Stack<String> stack = new Stack<>();
    int CAPACITY = 5;
 
    ReentrantLock lock = new ReentrantLock();
    Condition stackEmptyCondition = lock.newCondition();
    Condition stackFullCondition = lock.newCondition();
 
    public void pushToStack(String item){
        try {
            lock.lock();
            while(stack.size() == CAPACITY) {
                stackFullCondition.await();
            }
            stack.push(item);
            stackEmptyCondition.signalAll();
        } finally {
            lock.unlock();
        }
    }
 
    public String popFromStack() {
        try {
            lock.lock();
            while(stack.size() == 0) {
                stackEmptyCondition.await();
            }
            return stack.pop();
        } finally {
            stackFullCondition.signalAll();
            lock.unlock();
        }
    }
}

6. Заключение

В этой статье мы видели различные варианты реализации интерфейсов класса блокировка StampedLock и вновь введены. Мы также обсудим, как использовать класс Condition для обработки нескольких условий.

образ

Добро пожаловать на номер общественного внимания: « Java доверенного лица » номер общественного беспокойства, ответ « 1024 » вы знаете, получить бесплатные 30 классические книги по программированию . Я обеспокоен ходом с 100000 программистов. Java знания обновляются ежедневно О, с нетерпением ждем вашего приезда!

образ

рекомендация

отblog.csdn.net/feilang00/article/details/87912123