在单个 JVM 内和跨多个 JVM 使用 java 文件锁
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5715346/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using java file locks within single JVM and across multiple JVMs
提问by Yakov
I guess I miss something, but I cannot understand how file locks work in Java. To be more exact - how it is implemented.
我想我错过了一些东西,但我无法理解文件锁在 Java 中是如何工作的。更准确地说 - 它是如何实现的。
It seems I cannot acquire (even cannot attempt acquiring) two or more locks for the same file inside single JVM. First lock will be successfully acquired, all further attempts to acquire more locks will result in OverlapingFileLockException. Nevertheless it works for separate processes.
似乎我无法在单个 JVM 中为同一文件获取(甚至无法尝试获取)两个或多个锁。将成功获取第一个锁,所有进一步尝试获取更多锁都将导致 OverlapingFileLockException。尽管如此,它适用于单独的进程。
I want to implement data-storage backed by file-system which is intended to work with multiple concurrent requests (both read and write). I want to use file locks to lock on particular files in the storage.
我想实现由文件系统支持的数据存储,该文件系统旨在处理多个并发请求(读取和写入)。我想使用文件锁来锁定存储中的特定文件。
It seems that I have to introduce one more synchronization (exclusive) on JVM-level and only then sync on files to avoid this exception.
看来我必须在 JVM 级别再引入一个同步(独占),然后才同步文件以避免此异常。
Did anyone do anything like that?
有没有人做过这样的事情?
I prepared simple test case to show what my problem is. I use Mac OS X, Java 6.
我准备了简单的测试用例来说明我的问题是什么。我使用 Mac OS X,Java 6。
import junit.framework.*;
import javax.swing.*;
import java.io.*;
import java.nio.channels.*;
/**
* Java file locks test.
*/
public class FileLocksTest extends TestCase {
/** File path (on Windows file will be created under the root directory of the current drive). */
private static final String LOCK_FILE_PATH = "/test-java-file-lock-tmp.bin";
/**
* @throws Exception If failed.
*/
public void testWriteLocks() throws Exception {
final File file = new File(LOCK_FILE_PATH);
file.createNewFile();
RandomAccessFile raf = new RandomAccessFile(file, "rw");
System.out.println("Getting lock...");
FileLock lock = raf.getChannel().lock();
System.out.println("Obtained lock: " + lock);
Thread thread = new Thread(new Runnable() {
@Override public void run() {
try {
RandomAccessFile raf = new RandomAccessFile(file, "rw");
System.out.println("Getting lock (parallel thread)...");
FileLock lock = raf.getChannel().lock();
System.out.println("Obtained lock (parallel tread): " + lock);
lock.release();
}
catch (Throwable e) {
e.printStackTrace();
}
}
});
thread.start();
JOptionPane.showMessageDialog(null, "Press OK to release lock.");
lock.release();
thread.join();
}
/**
* @throws Exception If failed.
*/
public void testReadLocks() throws Exception {
final File file = new File(LOCK_FILE_PATH);
file.createNewFile();
RandomAccessFile raf = new RandomAccessFile(file, "r");
System.out.println("Getting lock...");
FileLock lock = raf.getChannel().lock(0, Long.MAX_VALUE, true);
System.out.println("Obtained lock: " + lock);
Thread thread = new Thread(new Runnable() {
@Override public void run() {
try {
RandomAccessFile raf = new RandomAccessFile(file, "r");
System.out.println("Getting lock (parallel thread)...");
FileLock lock = raf.getChannel().lock(0, Long.MAX_VALUE, true);
System.out.println("Obtained lock (parallel thread): " + lock);
lock.release();
}
catch (Throwable e) {
e.printStackTrace();
}
}
});
thread.start();
JOptionPane.showMessageDialog(null, "Press OK to release lock.");
lock.release();
thread.join();
}
}
回答by user207421
From the Javadoc:
来自 Javadoc:
File locks are held on behalf of the entire Java virtual machine. They are not suitable for controlling access to a file by multiple threads within the same virtual machine.
代表整个 Java 虚拟机持有文件锁。它们不适合控制同一虚拟机内的多个线程对文件的访问。
回答by Peter Lawrey
You can only acquire a lock once per file. Locks are not re-entrant AFAIK.
每个文件只能获得一次锁。锁不是可重入的 AFAIK。
IMHO: Using files to communicate between process is a very bad idea. Perhaps you will be able to get this to work reliably, let me know if you can ;)
恕我直言:使用文件在进程之间进行通信是一个非常糟糕的主意。也许你能让它可靠地工作,如果可以,请告诉我;)
I would have one and only one thread read/write in only one process.
我会在一个进程中只有一个线程读/写。
回答by aroth
Have you checked the documentation? The FileChannel.lock()
method returns an exclusivelock across the entirefile. If you want to have multiple locks active concurrently across different threads, then you cannot use this method.
你检查过文档吗?该FileChannel.lock()
方法返回整个文件的排他锁。如果您希望在不同线程间同时激活多个锁,则不能使用此方法。
Instead you need to use FileChannel.locklock(long position, long size, boolean shared)
in order to lock a specific region of the file. This will allow you to have multiple locks active at the same time, provided that each one is applied to a different region of the file. If you attempt to lock the same region of the file twice, you will encounter the same exception.
相反,您需要使用FileChannel.locklock(long position, long size, boolean shared)
以锁定文件的特定区域。这将允许您同时激活多个锁,前提是每个锁都应用于文件的不同区域。如果您尝试两次锁定文件的同一区域,您将遇到相同的异常。