如何在 Java RMI 中锁定文件?

问题描述

我正在使用 Java RMI 实现一个快速文件服务器,它有 2 个远程方法一个用于从服务器读取文件,另一个用于将其写入客户端。

我想锁定对同一文件的并发访问。例如,如果10个用户同时调用read()和write()远程方法,指定同一个文件:'foo.txt',我需要在第二次调用之前完全执行第一次调用,第二次调用是在第三次调用之前完全执行...

如果我在两个 RMI 方法中使用“同步”语句,如果不同的用户同时调用这些方法,指定不同的文件,我会失去效率。

另一方面,我不能使用 FileLock 类,因为:

“代表整个Java虚拟机持有文件锁。 它们不适合控制多个人对文件的访问 同一虚拟机中的线程。”

而在 RMI 中,同一个 JVM 中只有一个进程,它为每次远程调用执行新线程。

解决方法

您可以使用 ReadWriteLock 来处理每个文件的 Path 的读/写锁 - 但前提是您不运行 RMI 服务器的多个进程或期望这些文件在一台 RMI 服务器虚拟机之外更改。读取或写入的每个入口点都需要为所提供的路径定位 ReentrantReadWriteLock,例如在此处使用 getReadWriteLock(Path)

private static ConcurrentHashMap<Path,ReentrantReadWriteLock> LOCKS = new ConcurrentHashMap<>();
private static ReentrantReadWriteLock getReadWriteLock(Path path) {
    return LOCKS.computeIfAbsent(path,p -> new ReentrantReadWriteLock());
}

然后您自己的代码可以使用 readLock()writeLock() API 调用在没有写入发生时允许多个读取器。随着时间的推移,您需要做一些内务处理来清除不再使用的条目。