如何在不同的应用程序级别上锁定文件?

Edu*_*rch 6 java multithreading synchronization locking file

这是场景:我有一个在servlet容器中运行的多线程java Web应用程序.应用程序在servlet容器中多次部署.有多个servlet容器在不同的服务器上运行.

也许这个图表清楚地说明了:

server1
+- servlet container
   +- application1
   |  +- thread1
   |  +- thread2
   +- application2
      +- thread1
      +- thread2
server2
+- servlet container
   +- application1
   |  +- thread1
   |  +- thread2
   +- application2
      +- thread1
      +- thread2
Run Code Online (Sandbox Code Playgroud)

网络共享目录中有一个文件,所有这些线程都可以访问.他们经常访问该文件.大多数情况下,文件只能由这些线程读取.但有时它是写的.

我需要一个故障安全解决方案来同步所有这些线程,以保证数据的一致性.


无效的解决方案(正确):

  1. 使用java.nio.channels.FileLock
    我能够使用FileLock类同步来自不同服务器的线程.但是这对于同一进程(servlet容器)中的线程不起作用,因为文件锁在进程范围内可用.

  2. 使用单独的文件进行同步,
    我可以创建一个单独的文件,指示进程正在读取或写入文件.此解决方案适用于所有线程,但有几个缺点:

    • 性能.创建,删除和检查文件的操作相当慢.具有一个同步文件的低权重实现将阻止并行读取文件.
    • JVM崩溃后,同步文件将保留,从而需要手动清理.
    • 我们在删除网络文件系统上的文件时已经有了奇怪的问题.
  3. 使用消息传递
    我们可以实现一个消息传递系统,线程将使用它来协调文件访问.但这对于这个问题来说似乎太复杂了.再说一次:表现会很糟糕.

有什么想法吗?

Aar*_*lla 1

如果您只需要很少写入文件,那么如何以临时名称写入文件,然后使用重命名使其对读者“可见”?

不过,这只适用于 Unix 文件系统。在 Windows 上,您需要处理某些进程打开文件(用于读取)的情况。在这种情况下,重命名将会失败。再试一次,直到重命名成功。

我建议对此进行彻底测试,因为您可能会遇到拥塞:读取请求太多,写入器任务长时间无法替换文件。

如果是这种情况,请让读取器检查临时文件,并等待几分钟进行下一次读取,直到文件消失。