我正在尝试使用Java FileLock写入文件,禁止所有其他进程和线程从中读取或写入文件,直到我完成它为止。给定this question及其答案,在我看来,这是我想要的完美工具 - 文件访问的互斥锁。
但是,我非常关注JavaDocs:
中的这段文字代表整个Java虚拟机保存文件锁。他们 不适合控制多个线程对文件的访问 在同一个虚拟机中。
有人可以减轻我的恐惧还是指向正确的方向?听起来FileLock
根本不能用来保持文件中的不同线程,即使另一个线程已经获得它。如果是这种情况,是否有其他规范的Java方法可以保护其他线程?
答案 0 :(得分:4)
FileLock
是进程级别锁定,因此不会保护文件不受具有锁定的进程内多个线程的并发访问。
您需要使用FileLock
的组合来防止来自其他进程的并发访问以及一些其他同步机制(如用于访问文件的synchronized
方法)以防止并发通过自己的线程访问。
答案 1 :(得分:2)
我会按如下方式实现:
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
后面,该ConcurrentHashMap
维护密钥的静态FileProxy
(URI,或绝对路径,或其他一些文件不变)值(FileProxy
)对。每个Semaphore
维护一个充当互斥锁的operate
- 这是用一个许可证初始化的。调用静态FileProxy
方法时,如果不存在,则从URI创建新的FileOperator
;然后将FileProxy
添加到acquire
队列中;在互斥锁上调用FileOperator
以确保一次只能有一个线程对该文件进行操作;最后FileProxy
做了它的事。
在此实现中,永远不会从ConcurrentHashMap
中删除FileProxy
个对象 - 如果这是一个问题,那么解决方案是将WeakReference
个对象包装在SoftReference
或map.replace
这样可以对它们进行垃圾回收,然后在reference.get() == null
时调用loop {
; this is the color of green boxed monsters to attack
PixelSearch, X, Y, 0, 0, %A_ScreenWidth%, %A_ScreenHeight%, 0x00FF00, 0, fast
if (ErrorLevel = 0) {
MouseClick, left, %X%, %Y%
}
else {
; if no monster present in screen, press teleport to search monsters
Send {F1}
}
}
return
以确保只有一个帖子替换了GC的引用。