如何使用Java同步共享文件夹中的文件访问(或者:网络级别的ReadWriteLock)

时间:2021-07-29 13:29:31

I have multiple applications running in one virtual machine. I have multiple virtual machines running on one server. And I have multiple servers. They all share a file using a shared folder on linux. The file is read and written by all applications. During the write process no application is allowed to read this file. The same for writing: If an application is reading the file no application is allowed to write it.

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

How do I manage to synchronize the applications so they will wait for the write process to finish before they read, and vice versa? (the applications inside a vm have to be synchronized and also applications across servers)

如何设置同步应用程序,以便它们在读取之前等待写入过程完成,反之亦然? (必须同步vm中的应用程序以及跨服务器的应用程序)

Curent implementation uses "file semaphores". If the file is about to be written the application tries to "acquire" the semaphore by creating an additional file (lets name it "file.semaphore") in the shared folder. If the "file.semaphore" file already exists this means the semaphore is already locked by a different application. This approach has the problem that I cannot make sure that the "file exists"-test and "create file"- operation are executed atomic. This way it is possible that two applications test for the "file.semaphore" file, see it does not exist and try to create the file at the same time.

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

4 个解决方案

#1


3  

You can use NIO locking capabilities. See FileChannel#lock().

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

However, this will work only if underlying filesystem supports locking over the network. Recent NFS should support it. Probably, Samba supports them too, but can’t say for sure.

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

See article for example.

例如,参见文章。

#2


0  

Have a look at the Javadocs for the createNewFile() method - it specifically states that creating files is not a reliable method for synchronization, and recommends the FileLock class instead (it's another package in java.nio.channels so is essentially the same as what Ivan Dubrov is suggesting).

看一下createNewFile()方法的Javadocs - 它明确指出创建文件不是一种可靠的同步方法,而是建议使用FileLock类(它是java.nio.channels中的另一个包,所以基本上与Ivan Dubrov建议)。

This would imply that your identification of the problem is accurate, and no amount of playing around will solve this with traditional file creation. My first thought was to check the return code from createNewFile(), but if the Javadocs say it's not suitable then it's time to move on.

这意味着您对问题的识别是准确的,并且没有多少游戏可以解决传统文件创建问题。我的第一个想法是检查来自createNewFile()的返回码,但如果Javadocs认为它不合适,那么就该继续前进了。

#3


0  

Need to combine file locking for protection between JVM's with synchronization within threads of a given JVM. See the answer by cyber-monk here

需要将文件锁定与JVM的保护结合在一起,以便在给定JVM的线程内实现同步。在这里查看网络僧侣的答案

#4


0  

I am also trying to determine the best way to solve this problem for a similar situation (less participating processes, but still same underlying problem). If you haven't been able to employ the file locking scheme suggested by Ivan (e.g. system|language|network service does not support it), maybe you could designate one of the participants as a referee. All participants write unique semaphores, call them "participant#.request" when they want the file. The referee polls the file system for these semaphores. When he sees one, he writes back "participant#.lock", and deletes the request. If he happens to see multiple at the "same time" he selects one at random (or first by file modification time) and deletes only their request. Then, the participant issued the lock knows they can access the file safely. When the participant is done with the file, they delete their own lock. While there is a lock in place, no other locks are issued by the referee. Any requests that are present after the user deletes their lock could be served a new lock without issuing a new request, so you could have the other users poll for their lock after sending the request. Probably this is what the locking mechanism is doing anyway, except maybe for the ability to manage the lock as a queue that comes with requests being processed in the order they are received (i.e. if the referee uses modification time). Also, since you're in charge of the referee you could set timeouts to locks, allowing him issue timeout semaphores to the process that is hogging the file and then remove the lock (hoping of course that if that process with the lock died, it did so nicely).

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

#1


3  

You can use NIO locking capabilities. See FileChannel#lock().

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

However, this will work only if underlying filesystem supports locking over the network. Recent NFS should support it. Probably, Samba supports them too, but can’t say for sure.

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

See article for example.

例如,参见文章。

#2


0  

Have a look at the Javadocs for the createNewFile() method - it specifically states that creating files is not a reliable method for synchronization, and recommends the FileLock class instead (it's another package in java.nio.channels so is essentially the same as what Ivan Dubrov is suggesting).

看一下createNewFile()方法的Javadocs - 它明确指出创建文件不是一种可靠的同步方法,而是建议使用FileLock类(它是java.nio.channels中的另一个包,所以基本上与Ivan Dubrov建议)。

This would imply that your identification of the problem is accurate, and no amount of playing around will solve this with traditional file creation. My first thought was to check the return code from createNewFile(), but if the Javadocs say it's not suitable then it's time to move on.

这意味着您对问题的识别是准确的,并且没有多少游戏可以解决传统文件创建问题。我的第一个想法是检查来自createNewFile()的返回码,但如果Javadocs认为它不合适,那么就该继续前进了。

#3


0  

Need to combine file locking for protection between JVM's with synchronization within threads of a given JVM. See the answer by cyber-monk here

需要将文件锁定与JVM的保护结合在一起,以便在给定JVM的线程内实现同步。在这里查看网络僧侣的答案

#4


0  

I am also trying to determine the best way to solve this problem for a similar situation (less participating processes, but still same underlying problem). If you haven't been able to employ the file locking scheme suggested by Ivan (e.g. system|language|network service does not support it), maybe you could designate one of the participants as a referee. All participants write unique semaphores, call them "participant#.request" when they want the file. The referee polls the file system for these semaphores. When he sees one, he writes back "participant#.lock", and deletes the request. If he happens to see multiple at the "same time" he selects one at random (or first by file modification time) and deletes only their request. Then, the participant issued the lock knows they can access the file safely. When the participant is done with the file, they delete their own lock. While there is a lock in place, no other locks are issued by the referee. Any requests that are present after the user deletes their lock could be served a new lock without issuing a new request, so you could have the other users poll for their lock after sending the request. Probably this is what the locking mechanism is doing anyway, except maybe for the ability to manage the lock as a queue that comes with requests being processed in the order they are received (i.e. if the referee uses modification time). Also, since you're in charge of the referee you could set timeouts to locks, allowing him issue timeout semaphores to the process that is hogging the file and then remove the lock (hoping of course that if that process with the lock died, it did so nicely).

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