5

我有多个应用程序在一台虚拟机中运行。我有多个虚拟机在一台服务器上运行。我有多个服务器。他们都使用 linux 上的共享文件夹共享一个文件。该文件由所有应用程序读取和写入。在写入过程中,不允许任何应用程序读取此文件。写入也是如此:如果应用程序正在读取文件,则不允许应用程序写入文件。

我如何设法同步应用程序,以便它们在读取之前等待写入过程完成,反之亦然?(虚拟机内的应用程序必须同步,跨服务器的应用程序也必须同步)

当前的实现使用“文件信号量”。如果文件即将被写入,应用程序会尝试通过在共享文件夹中创建一个附加文件(让我们将其命名为“file.semaphore”)来“获取”信号量。如果“file.semaphore”文件已经存在,这意味着信号量已经被另一个应用程序锁定。这种方法的问题是我无法确保“文件存在”-测试和“创建文件”-操作是原子执行的。这样,两个应用程序可能会测试“file.semaphore”文件,发现它不存在并尝试同时创建该文件。

4

4 回答 4

4

您可以使用 NIO 锁定功能。请参阅FileChannel#lock()

但是,这只有在底层文件系统支持网络锁定时才有效。最近的 NFS 应该支持它。可能 Samba 也支持它们,但不能肯定地说。

例如见文章。

于 2008-11-26T09:56:17.150 回答
0

查看createNewFile()方法的 Javadocs - 它明确指出创建文件不是一种可靠的同步方法,并推荐使用FileLock类(它是 java.nio.channels 中的另一个包,因此与伊万杜布罗夫建议)。

这意味着您对问题的识别是准确的,使用传统的文件创建方法再多的尝试也无法解决这个问题。我的第一个想法是检查 createNewFile() 的返回代码,但如果 Javadocs 说它不合适,那么是时候继续了。

于 2009-01-23T12:15:55.077 回答
0

需要将用于保护 JVM 之间的文件锁定与给定 JVM 的线程内的同步结合起来。在此处查看网络僧侣的答案

于 2014-10-17T14:16:22.173 回答
0

我也在尝试确定在类似情况下解决此问题的最佳方法(参与过程较少,但仍然存在相同的潜在问题)。如果您无法使用 Ivan 建议的文件锁定方案(例如系统|语言|网络服务不支持它),也许您可​​以指定其中一位参与者作为裁判。所有参与者都编写独特的信号量,当他们想要文件时称他们为“participant#.request”。裁判轮询这些信号量的文件系统。当他看到一个时,他回写“participant#.lock”,并删除该请求。如果他碰巧在“同时”看到多个,他会随机选择一个(或首先按文件修改时间)并仅删除他们的请求。然后,发布锁的参与者知道他们可以安全地访问文件。当参与者完成文件后,他们会删除自己的锁。当有锁到位时,裁判不会发出其他锁。用户删除锁后出现的任何请求都可以在不发出新请求的情况下获得新锁,因此您可以让其他用户在发送请求后轮询他们的锁。无论如何,这可能是锁定机制正在做的事情,除了将锁定作为队列管理的能力,该队列伴随着请求的接收顺序被处理(即,如果裁判使用修改时间)。此外,由于您负责裁判,您可以设置锁定超时,允许他向占用文件的进程发出超时信号,然后删除锁定(当然希望如果该锁定的进程死亡,它做得很好)。

于 2017-07-14T11:34:17.080 回答