Освобождает ли вызов метода RMI синхронизированную блокировку?

Я вызываю метод RMI, и он находится внутри синхронизированного блока. Что-то вроде этого, где метод appendEntries является вызываемым методом RMI:

public void run() {
    synchronized(matchIndex.get(followerId)) {
        ArrayList<Entry> reqs = new ArrayList<>();
        for (int i = matchIndex.get(followerId) + 1; i <= log.lastIndex(); i++) {
            reqs.add(log.get(i));
        }
   
        try {
            answer = server.serverList.get(followerId).appendEntries(reqs);
            if (answer.isSuccessful()) {
                matchIndex.replace(followerId, matchIndex.get(followerId) + reqs.size());
            } else {
                System.out.println("Not Successfull.");
            }
        } catch (Exception e) {
            e.printStackTrace();    
        }
    }
}    

Пока этот поток ожидает ответа метода RMI, освобождает ли он блокировку в matchIndex.get(followerId)?

Для лучшего контекста я спрашиваю об этом, потому что, по-видимому, при использовании различных потоков и отсутствии неудачных ответов возникает случайная точка, когда два потока вызывают appendEntries для одного и того же followerId, а затем общая запись в reqs, чего не должно происходить и Подозреваю, что причина в этом.

Если вам нужны дополнительные пояснения, я реализую алгоритм консенсуса Raft для классового проекта. Если вы не знакомы с этим, в основном этот упрощенный фрагмент кода является частью логики Лидера, и он должен отправлять записи, которые есть в его журнале, своим Последователям. Журналы на лидере и на последователях должны быть в конечном счете непротиворечивыми. Этот фрагмент кода находится в потоке, который вызывается, когда Лидер хочет отправить свои записи журнала определенному ведомому, но он не должен вызывать метод appendEntries более одного раза за раз для каждого ведомого. matchIndex — это позиции последней записи, известные лидеру для каждого последователя.

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


person sfmelo    schedule 10.11.2020    source источник
comment
Нет, вызов RMI не должен снимать блокировку. Но похоже, что вы вмешиваетесь в то, что блокируете. Этот вызов замены выглядит так, как будто он подрывает вашу схему блокировки.   -  person Nathan Hughes    schedule 10.11.2020
comment
Нет, это не так. С точки зрения JVM вызов удаленного метода ничем не отличается от вызова локального метода.   -  person user207421    schedule 11.11.2020


Ответы (1)


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

person sfmelo    schedule 10.11.2020