首页 > 解决方案 > 调用 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)

为了更好的上下文,我问这个是因为,显然,在使用各种线程并且没有不成功的答案的情况下,出现了一个随机点,两个线程分别调用 appendEntriesfollowerId和一个公共 Entry in reqs,这不应该发生,我怀疑这就是原因。

如果您需要进一步解释,我正在为一个类项目实现共识算法 Raft。如果您不熟悉它,基本上这段简化的代码是“Leader”逻辑的一部分,他必须将其日志中的条目发送给他的“Followers”。领导者和追随者的日志必须最终保持一致。这段代码在一个线程上,当“Leader”想要将其日志条目发送给特定的追随者时调用,但他不应该appendEntries为每个追随者一次多次调用该方法。这matchIndex是领导者知道的每个追随者的最后一个条目的位置。

我希望这不是太多或太少的信息,这是我使用本网站多年后的第一个 Stack Overflow 问题,任何帮助将不胜感激。

标签: javamultithreadingrmithread-synchronizationraft

解决方案


正如@NathanHughes 指出的那样,我的问题是我在拥有锁的对象上使用了 replace 方法,它弄乱了同步。我专门为锁定目的创建了一个新的对象数组,它现在可以完美运行。


推荐阅读