我正在使用Java在多线程服务器上工作。 服务器监视文件目录。客户可以向服务器询问:
要进行传输,我计划通过transferFrom和transferTo方法使用FileChannels和SocketChannels。根据文档,这两种方法是线程安全的。 事实是,仅调用这两个函数不足以完全读取/写入文件。
如果同一文件上同时有多个请求,则会出现问题。在这种情况下,多个线程可能在同一文件上执行读/写操作。现在,根据Java文档,对transferFrom / transferTo的单个调用是线程安全的。但是,仅对这两个函数的调用不足以完全读取/写入文件。如果线程A答复下载请求,而线程B答复引用同一文件的上传请求,则可能会发生以下情况:
在这种情况下,下载客户端会收到旧版本的一部分和新版本的一部分。
为解决这个问题,我认为我应该使用某种锁定方式,但是我不确定如何高效地进行锁定。我可以创建两个用于读取和写入的同步方法,但是显然会产生太多争用。
我想到的最佳解决方案是使用锁条。在执行任何读/写操作之前,将计算基于文件名的哈希。然后,获取位置lockArr [hash%numOfLocks]的锁定。 我还认为我应该使用ReadWriteLocks,因为应该允许多个同时读取。
现在,这是我对问题的分析,我可能完全错了。有更好的解决方案吗?
答案 0 :(得分:3)
锁定意味着有人必须等待别人-并非最佳解决方案。
客户端上传文件时,应将其写到同一磁盘(通常在同一目录中)中的临时文件中,然后在文件上传完成后:
在典型的实现中,您需要一个集中化的类(将其称为ConcurrentFileAccessor
)来管理线程之间的交互。
读者将需要向此类注册,并在实际的阅读操作中对某些对象进行同步。上传完成后,编写者将必须要求所有这些锁定来阻止读取,关闭所有读取的文件,重命名旧版本,重新打开,查找并释放它们,以允许读者继续。