首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何锁定文件

如何锁定文件
EN

Stack Overflow用户
提问于 2012-07-18 14:40:03
回答 2查看 7.3K关注 0票数 4

我有一个write方法,它应该安全地将数据写入文件。

代码语言:javascript
复制
// 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!!");
  }
}

虽然我知道它有一些皱纹,但它现在对我来说已经很好了。

我最近更改了一个项目,该项目使用此代码在Java 5下构建和运行(来自Java 6),现在它看起来陷入了僵局,等待文件上的锁。它是一个多线程应用程序,几个线程很可能尝试写入同一个文件。

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

一些研究提出了一个有趣的小金块,其中提到:

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

那我是不是做错了?如果是的话,正确的方法是什么?如果我做得对,我怎么会陷入僵局?

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

还补充道:,我确实已经使用各种synchronized机制解决了这个问题。然而,我确实有一些悬而未决的问题:

  1. 为什么FileLock lock = file.getChannel().lock(); 不适合
  2. 为什么我的问题只出现在切换回Java-5时,当Java-6一切正常的时候?
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-07-18 15:20:48

FileLock只用于进程间锁定,javadoc读取:

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

要在java线程(同一个JVM)之间锁定,需要使用一些共享锁。我建议在文件编写类中使用同步块( 根据 to 这些 文章可能执行得最好):

代码语言:javascript
复制
final Object lock = new Object();

public void write(...){
  synchronized(lock){
    // do writing
  }
}

另一种方法是使用ReentrantLock,然后使用已证实的

代码语言:javascript
复制
final ReentrantLock lock = new ReentrantLock();

public void write(...){
  try {
    lock.lock()
    // do the writing
  } finally {
    // forget this and you're screwed
    lock.unlock();
  }
}
票数 4
EN

Stack Overflow用户

发布于 2012-07-18 14:44:11

您可能需要使用文件而不是hashmap在实际代码上实现关键部分概念。您可以创建一个同步块,也可以将文件访问代码分离为一个单独的过程,并使该方法同步。

实际上,一次只执行一个同步块。它给了你你所需要的独家访问权。

另一种方法是使用串行线程执行器,这取决于您的功能需求。

您可能想看看这个线程:如何使用Java (网络级别上的OR: ReadWriteLock )同步共享文件夹中的文件访问

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11543967

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档