代码之家  ›  专栏  ›  技术社区  ›  Miles D

网络上的Java文件锁定

  •  12
  • Miles D  · 技术社区  · 17 年前

    这可能与之前的帖子类似,但我想具体说明在网络上而不是在本地使用锁定。我想将文件写入共享位置,这样它就可以在网络上运行(当然是Windows网络,也许是Mac)。我想防止其他人在写入此文件时读取其任何部分。这不是一个高度并发的进程,文件通常小于10MB。

    我读过 FileLock 文件和 File 文档和我有点困惑,什么是安全的,什么是不安全的。我想锁定整个文件,而不是部分文件。

    我能用吗 FileChannel.tryLock() ,它在网络上是安全的,还是取决于网络的类型?它能在标准的Windows网络上工作吗(如果有的话)。

    如果这不起作用,最好创建一个零字节的文件或目录作为锁文件,然后写出主文件。为什么 File.createNewFile() 文档说不要用它来锁定文件?我理解这取决于比赛条件,并不理想。

    4 回复  |  直到 17 年前
        1
  •  7
  •   Desmond Desmond    17 年前

    这在网络文件系统上无法可靠地完成。只要您的应用程序是唯一访问该文件的应用程序,最好实现某种协作锁定过程(可能是在打开文件时将锁定文件写入网络文件系统)。然而,不建议这样做的原因是,如果您的进程崩溃或网络崩溃或发生任何其他问题,您的应用程序将进入一个令人讨厌的肮脏状态。

        2
  •  4
  •   D-Mac    13 年前

    您可以在要写入的服务器上有一个空文件。

    当你想写入服务器时,你可以捕获令牌。只有当你有令牌时,你才应该写入服务器上的任何文件。

    当您准备好进行文件操作或抛出异常时,您必须释放令牌。

    辅助类可以如下所示

    private FileLock lock;
    
    private File tokenFile;
    
    public SLTokenLock(String serverDirectory) {
        String tokenFilePath = serverDirectory + File.separator + TOKEN_FILE;
        tokenFile = new File(tokenFilePath);
    }
    
    public void catchCommitToken() throws TokenException {
        RandomAccessFile raf;
        try {
            raf = new RandomAccessFile(tokenFile, "rw"); //$NON-NLS-1$
            FileChannel channel = raf.getChannel();
            lock = channel.tryLock();
    
            if (lock == null) {
                throw new TokenException(CANT_CATCH_TOKEN);
            }
        } catch (Exception e) {
            throw new TokenException(CANT_CATCH_TOKEN, e);
        }
    }
    
    public void releaseCommitToken() throws TokenException {
        try {
            if (lock != null && lock.isValid()) {
                lock.release();
            }
        } catch (Exception e) {
            throw new TokenException(CANT_RELEASE_TOKEN, e);
        }
    }
    

    那么,你的操作应该如下

    try {
            token.catchCommitToken();
    
            // WRITE or READ to files inside the directory
        } finally {
            token.releaseCommitToken();
        }
    
        3
  •  3
  •   Markus Lausberg    17 年前

    我发现了这个bug报告,它描述了为什么在file.createNewFile文档中添加了关于文件锁定的注释。

    http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4676183

    它指出:

    如果将文件标记为deleteOnExit 之前 调用createNewFile但该文件已存在,您可能会删除一个不是您创建的文件并删除其他人的锁!另一方面,如果你标记文件 之后 创建它,您将失去原子性:如果程序在文件被标记之前退出,它将不会被删除,锁将被“楔入”。

    因此,File.createNewFile()不鼓励锁定的主要原因似乎是,如果JVM在您有机会删除之前意外终止,您最终可能会得到孤立的锁文件。如果您可以处理孤立的锁定文件,那么它可以用作一种简单的锁定机制。但是,我不建议使用错误报告注释中建议的方法,因为它在读/写时间戳值和回收过期锁方面有竞争条件。

        4
  •  1
  •   Nicholas    17 年前

    与其实施一种锁定策略,该策略很可能依赖于读者遵守您的约定,但不会强迫他们遵守,也许您可以将文件写入一个隐藏或名称模糊的文件,在那里它对读者来说是不可见的。写入操作完成后,将文件重命名为预期的公共名称。

    缺点是,在没有额外IO的情况下隐藏和/或重命名可能需要您使用本机操作系统命令,但这样做的过程应该相当简单和确定。