我试图使用Java FileLock向文件写入,以禁止所有其他进程和线程从文件中读取或写入文件,直到完成为止。考虑到这个问题和它的答案,在我看来,这是我想要的完美工具--一个用于文件访问的互斥体。
然而,我非常关注JavaDocs的这篇文章。
文件锁代表整个Java虚拟机持有。它们不适合通过同一虚拟机中的多个线程来控制对文件的访问。
有人可以减轻我的恐惧或者指出我的正确方向吗?听起来,即使另一个线程已经获得了文件,FileLock也根本无法将一个不同的线程排除在文件之外。如果是这样的话,是否还有另一种规范的Java方法可以保护其他线程免受其他线程的影响呢?
发布于 2015-05-19 21:12:59
FileLock是进程级别的锁,因此不会保护文件不受具有锁的进程中的多个线程的并发访问。
您需要使用FileLock的组合来防止来自其他进程的并发访问,以及进程中的其他同步机制(例如访问文件的synchronized方法),以防止您自己的线程进行并发访问。
发布于 2015-05-19 21:52:46
我将按以下方式执行:
interface FileOperator {
public void operate(File file);
}
class FileProxy {
private static final ConcurrentHashMap<URI, FileProxy> map =
new ConcurrentHashMap<>();
private final Semaphore mutex = new Semaphore(1, true);
private final File file;
private final URI key;
private FileProxy(File file) {
this.file = file;
this.key = file.toURI();
}
public static void operate(URI uri, FileOperator operator) {
FileProxy curProxy = map.get(uri);
if(curProxy == null) {
FileProxy newProxy = new FileProxy(new File(uri));
FileProxy curProxy = map.putIfAbsent(newProxy.key, newProxy);
if(curProxy == null) {
curProxy = newProxy; // FileProxy was not in the map
}
}
try {
curProxy.mutex.acquire();
operator.operate(curProxy.file);
} finally {
curProxy.mutex.release();
}
}
}使用文件的线程实现FileOperator或类似的东西。文件隐藏在FileProxy后面,它维护密钥(URI、绝对路径或其他文件不变)值(FileProxy)对的静态ConcurrentHashMap。每个FileProxy都维护一个充当互斥体的Semaphore --这是用一个许可来初始化的。当调用静态operate方法时,如果不存在,则从URI中创建一个新的FileProxy;然后将FileOperator添加到FileProxy队列;在互斥体上调用acquire,以确保一次只能对文件进行一个线程操作;最后,FileOperator完成其任务。
在这个实现中,FileProxy对象永远不会从ConcurrentHashMap中移除--如果这是一个问题,那么解决方案是将FileProxy对象包装在WeakReference或SoftReference中,以便能够垃圾收集它们,然后调用map.replace if reference.get() == null,以确保只有一个线程替换GC的引用。
https://stackoverflow.com/questions/30336109
复制相似问题