问题描述
我正在使用 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 调用在没有写入发生时允许多个读取器。随着时间的推移,您需要做一些内务处理来清除不再使用的条目。