【发布时间】:2012-07-17 15:24:00
【问题描述】:
我有一个write 方法,应该可以安全地将数据写入文件。
// 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() 调用返回。
一些研究提出了这个有趣的小nugget,其中提到:
代表整个 Java 虚拟机持有文件锁。 它们不适合控制同一虚拟机内的多个线程对文件的访问。
那我做错了吗?如果是这样,正确的方法是什么?如果我做得对,我怎么会陷入僵局?
补充:忘了提 - 每个线程都有自己的这个对象的副本,所以代码中不应该有任何同步问题。我觉得依靠FileChannel.lock() 方法来确保写入不会交错是安全的。
也添加了:我确实使用各种synchronized 机制解决了这个问题。但是,我确实有一些悬而未决的问题:
- 为什么
FileLock lock = file.getChannel().lock();不适合...? - 为什么在 Java-6 一切正常的情况下切换回 Java-5 时才出现我的问题?
【问题讨论】:
-
如果你是唯一的作者,为什么要锁定文件?你想解决什么问题?我不会使用锁,因为它们会导致比解决的问题更多的问题。
-
我正在锁定文件以避免交叉写入。文件锁会导致什么问题?
标签: java multithreading file file-io locking