Java中的文件系统锁

时间:2014-04-28 23:08:17

标签: java io nio

在从文件中读取行并处理它们时,我在某些代码中使用了文件系统锁。这是因为我的架构有多个应用服务器;我只希望一台服务器处理每一行以避免数据重复。

我在辅助方法中创建了一个DTO。该对象使用锁定详细信息填充,该详细信息可以由辅助方法返回,并且可以随后查询以查看锁定是否成功。如果是,则可以处理文件中的行。

通常,如果两个服务器同时尝试并处理文件中的行,则其中一个服务器会抛出异常,因为该文件已被另一个文件锁定。如果发生这种情况,我的代码会捕获异常并移动到文件的下一行。

锁定在下面实现:

String filename = <Unique identifier of record being processed>;
File lockfile = new File(System.getProperty("java.io.tmpdir"), filename);
RandomAccessFile randomAccessfile = new RandomAccessFile(lockfile, "rw");
FileChannel fileChannel = randomAccessfile.getChannel();

FileLockDTO fileLockDTO = new FileLockDTO();
fileLockDTO.setLockedfile(lockfile);
fileLockDTO.setRandomAccessfile(randomAccessfile);
fileLockDTO.setFileLock(fileChannel.tryLock()); 

在绝大多数情况下,代码运行良好。但是在极少数情况下会出现重复记录,这表明存在一个边缘情况,其中多个应用程序服务器似乎在同一时刻创建锁。

我长得很长努力学习代码并尝试了大量的测试,但无法确定这将如何发生。只是想知道是否有人有任何想法?

提前感谢您的任何帮助。

2 个答案:

答案 0 :(得分:-1)

来自FileLock javadocs:

  

锁是否实际阻止其他程序访问锁定区域的内容是系统相关的,因此未指定。某些系统的本机文件锁定工具仅仅是建议性的,这意味着程序必须协作地观察已知的锁定协议,以保证数据的完整性。

来自FileChannel.tryLock() javadocs :(重点是我的)OverlappingFileLockException被抛出

  

如果与此请求区域重叠的锁已由此Java虚拟机保留,或者另一个线程已在此方法中被阻止并且正在尝试锁定重叠区域

以下是您的应用的简单失败方案:

  1. 服务器A查询资源1上是否存在锁定=&gt;返回false
  2. 服务器B查询资源1 =&gt;上是否存在锁定返回false
  3. 服务器A在上面的代码段中运行第1-4行并成功
  4. 服务器B在上面的代码片段中运行1-4行并成功(什么会阻止它?)
  5. 服务器A创建DTO
  6. 服务器B创建DTO(取决于操作系统,对tryLock()的调用可能无法阻止任何事情)
  7. 服务器A处理“已锁定”记录
  8. 服务器B处理“锁定”记录

答案 1 :(得分:-1)

你必须依赖FileLockDTO.setFileLock()中的null检查,或者你拥有它的任何地方,如果确实你拥有它。这一切对我来说似乎太精致了。我只想锁定你正在阅读的实际文件的实际行,而不是引入这些二级锁文件。然后,如果您遇到现有锁,您就会跳过该行。或者使用一种数据结构,它只能传递一行,并消除整个问题,例如某种类型的MQ或数据库。

编辑关于FileLocks无法跨JVM或进程工作的理论的下载者和/或拥护者需要阅读文档。