Могу ли я изменить ReentrantLock, чтобы его можно было использовать с попыткой использования ресурсов?

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

Идея состоит в том, чтобы реализовать класс ReentrantLock, который можно использовать с «попробовать с ресурсами», а это означает, что он должен реализовать интерфейс AutoCloseable.

Кроме того, я хотел спросить, почему в методе main компилятор выдает, что я должен добавить предложение catch, потому что мой метод close (в MyReentrantLock) не генерирует исключение.

import java.util.concurrent.locks.ReentrantLock;

public class Ex09ReentrantLock {

    @SuppressWarnings("serial")
    public static class MyReentrantLock extends ReentrantLock implements AutoCloseable{

        public MyReentrantLock() {
            super();
            lock();
        }

        @Override
        public void close(){        
            unlock();
        }   
    }

    public static AutoCloseable lock() {

        var locker = new MyReentrantLock(); //lock() is called in the constructor

        return locker;  //implements AutoCloseable          
    }


    //Demo 
    public static void main(String[] args) {

        //try(ReentrantLock lock = new ReentrantLock()){} = compiler error

        try(var locker = lock();){          
            //some work...          
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }           
    }
}
  1. Подходит ли эта реализация? (вызвать блокировку в конструкторе...)

  2. Почему компилятор заставляет меня добавлять предложение catch(), если мое закрытие не вызывает исключение?


person Hodiya Eyal    schedule 02.12.2019    source источник
comment
Чтобы ответить на ваш второй вопрос: это заставляет вас поймать Exception, потому что ваш метод #lock() возвращает AutoCloseable, чей метод #close() делает объявляет себя выдающим упомянутое исключение. Поскольку возвращаемый объявленный тип — AutoCloseable, компилятор понятия не имеет, что реализация не имеет объявления throws. Ваш метод должен будет вернуть MyReentrantLock, чтобы компилятор знал такую ​​информацию.   -  person Slaw    schedule 02.12.2019


Ответы (1)


Блокировки предназначены для совместного использования. Замок, который блокирует строительство, может быть заблокирован только с помощью new и, следовательно, не может использоваться совместно, что означает его бесполезность.

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

Судя по тому, что вы поделились, наиболее близким к тому, что вы выразили, является ключевое слово synchronized.

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

person Antoine Marques    schedule 02.12.2019
comment
Просто отметим, что в отношении вашего последнего абзаца в Java механизм synchronized фактически предшествует Lock (добавлен в Java 5). Если я правильно помню, какое-то время Lock API действительно работал значительно лучше в условиях конкуренции, но я считаю, что это уже не так в более новых версиях (нет доступных источников). - person Slaw; 02.12.2019
comment
Не уверен, правильно ли я понимаю, что вы имеете в виду, но synchronized использует блокировки монитора (реализованные изначально), которые отличаются от высокоуровневого API блокировок. Однажды я построил Lock с помощью мониторов, чтобы иметь возможность использовать механизм synchronized через Lock API, используя несколько скрытую функцию, позволяющую вручную входить или выходить из внутренней блокировки объекта. - person Antoine Marques; 02.12.2019
comment
Ваш последний абзац подразумевает для меня, что synchronized был создан в ответ на некоторые неудачи/трудности Lock. Теперь, возможно, вы ссылаетесь на историю программирования в целом, но в Java Lock было добавлено много версий после synchronized. Я почти уверен, что Lock был добавлен для обеспечения функциональности, которую synchronized предоставить не может. И мое второе предложение касалось некоторых тестов, о которых я помню, читал; при первом добавлении Lock API работал лучше, чем synchronized, но я считаю, что они соответствовали друг другу в последних версиях Java. - person Slaw; 02.12.2019
comment
Хорошо, спасибо, я понимаю, что означают предыдущие даты в этом случае. - person Antoine Marques; 02.12.2019
comment
Конечно, ты прав. Блокировки монитора используются низкоуровневым API для реализации параллелизма, например реализации пакета java.concurrent. Замки - это объект более высокого уровня. Ключевым словом Synchronized был «безопасный» доступ высокого уровня к функциям низкого уровня, таким как Objet.wait/notify. - person Antoine Marques; 02.12.2019
comment
Для справки, блокировки монитора могут быть заключены в класс Lock с помощью docjar. com/docs/api/sun/misc/Unsafe.html - person Antoine Marques; 02.12.2019