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

网络上的Java文件锁定

  •  11
  • Miles D  · 技术社区  · 16 年前

    FileLock 文件和 File

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

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

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

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

        2
  •  4
  •   D-Mac    12 年前

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

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

    如果将文件标记为deleteOnExit 之前 之后 创建它,您将失去原子性:如果程序在标记文件之前退出,它将不会被删除,锁将被“楔入”。

        3
  •  3
  •   Markus Lausberg    16 年前

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

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

    helper类可以看起来像

    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();
        }
    
        4
  •  1
  •   Nicholas    16 年前

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