如何锁定文件 [英] How to lock a file

查看:177
本文介绍了如何锁定文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

     //我正在写的当前文件。 
FileOutputStream file = null;
...
//同步版本。
private void write(byte [] bytes){
if(file!= null&& file.getChannel()!= null){
try {
boolean written = false;
do {
try {
//锁定它!
FileLock lock = file.getChannel()。lock();
尝试{
//写入字节。
file.write(bytes);
写入= true;
} finally {
//释放锁。
lock.release();
}

} catch(OverlappingFileLockException ofle){
尝试{
//稍等一下
Thread.sleep(0);
} catch(InterruptedException ex){
throw new InterruptedIOException(Interrupted waiting a file lock。);


} while(!written);
} catch(IOException ex){
log.warn(无法锁定+ fileName,ex);

} else {
log.warn(Failing - +(file == null?file:channel)+is null !!);






$ b

现在我工作的很好,虽然我知道它有一些皱纹。

我最近更改了一个使用此代码在Java 5(从Java 6)下构建和运行的项目,现在它看起来像死锁,等待文件锁定。这是一个多线程的应用程序,这是很可能的几个线程试图写入到同一个文件。

调试器告诉我挂起的线程正在等待 FileLock lock = file.getChannel()。lock() call to return。



nugget 中提到:


文件锁代表整个Java虚拟机。 它们不适用于控制同一个虚拟机内的多个线程对文件的访问。

我做错了吗?如果是这样,什么是正确的方式?如果我这样做是正确的我怎么来打一个僵局?

补充:忘了提及 - 每个线程拥有自己的这个对象的副本所以在代码中不应该有任何同步问题。我觉得依靠 FileChannel.lock()方法是安全的,以确保写入不会交错。

也添加了:我确实已经使用各种 synchronized 机制解决了这个问题。为什么是 FileLock lock = file.getChannel()。lock()是什么意思_翻译_中文意思_ShowXiu翻译。 ); 不适合... ?

  • 为什么我的问题只在切换回Java-5时才会出现使用Java-6?


  • 解决方案 c>仅用于进程间锁定, javadoc 读取:
    $ b


    文件锁定代表整个Java虚拟机。
    它们不适用于控制同一个虚拟机中多个
    线程对文件的访问


    要锁定Java线程(相同的JVM)之间,你需要使用一些共享锁。我建议在文件写入类中使用同步块(即根据 这些 articles 可能表现最好):

      final Object lock = new Object(); 
    $ b public void write(...){
    synchronized(lock){
    // do writing
    }
    }

    另一种方法是使用 ReentrantLock ,然后使用成熟的习惯用语

      final ReentrantLock lock = new ReentrantLock(); 
    $ b $ public void write(...){
    try {
    lock.lock()
    //写作
    } finally {
    //忘记这个,你被搞砸了
    lock.unlock();
    }
    }


    I have a write method that is supposed to safely write data to a file.

    // The current file I am writing to.
    FileOutputStream file = null;
    ...
    // Synchronized version.
    private void write(byte[] bytes) {
      if (file != null && file.getChannel() != null) {
        try {
          boolean written = false;
          do {
            try {
              // Lock it!
              FileLock lock = file.getChannel().lock();
              try {
                // Write the bytes.
                file.write(bytes);
                written = true;
              } finally {
                // Release the lock.
                lock.release();
              }
    
            } catch (OverlappingFileLockException ofle) {
              try {
                // Wait a bit
                Thread.sleep(0);
              } catch (InterruptedException ex) {
                throw new InterruptedIOException("Interrupted waiting for a file lock.");
              }
            }
          } while (!written);
        } catch (IOException ex) {
          log.warn("Failed to lock " + fileName, ex);
        }
      } else {
        log.warn("Failing - " + (file == null ? "file" : "channel") + " is null!!");
      }
    }
    

    It has worked fine for me for a while now, although I know there are some wrinkles in it.

    I have recently changed a project that uses this code to build and run under Java 5 (from Java 6) and now it looks like it is deadlocked awaiting a lock on the file. It is a multithreaded app and it is quite possible for several threads to attempt to write to the same file.

    The debugger tells me that the hung threads are waiting for the FileLock lock = file.getChannel().lock() call to return.

    Some research brought up this interesting little nugget which mentions:

    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.

    So am I doing it wrong? If so what is the right way? If I am doing it right how come I hit a deadlock?

    Added: Forgot to mention - each thread holds its own copy of this object so there should not be any synchronisation issues within the code. I felt safe to rely on the FileChannel.lock() method to ensure writes do not interleave.

    Added too: I have indeed solved the issue using various synchronized mechanisms. I do, however, have outstanding questions:

    1. Why is FileLock lock = file.getChannel().lock(); not suitable ...?
    2. Why did my issues only appear when switching back to Java-5 when everything worked fine with Java-6?

    解决方案

    FileLock is only for interprocess locking, javadoc reads:

    "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."

    To lock between java threads (same JVM) you need to use some shared lock. I would suggest within the file writing class to use a synchronized block (which according to these articles is likely to perform best):

    final Object lock = new Object();
    
    public void write(...){
      synchronized(lock){
        // do writing
      }
    }
    

    Another approach is to use a ReentrantLock and then use the proven idiom of

    final ReentrantLock lock = new ReentrantLock();
    
    public void write(...){
      try {
        lock.lock()
        // do the writing
      } finally {
        // forget this and you're screwed
        lock.unlock();
      }
    }
    

    这篇关于如何锁定文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆