我有一种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()
调用返回。
一些研究提出了这个有趣的小金块,其中提到:
文件锁代表整个 Java 虚拟机持有。它们不适用于控制同一虚拟机内的多个线程对文件的访问。
那我做错了吗?如果是这样,正确的方法是什么?如果我做得对,我怎么会陷入僵局?
补充:忘了提 - 每个线程都有自己的这个对象的副本,所以代码中不应该有任何同步问题。我觉得依靠这种FileChannel.lock()
方法来确保写入不会交错是安全的。
也补充说:我确实使用各种synchronized
机制解决了这个问题。但是,我确实有一些悬而未决的问题:
- 为什么
FileLock lock = file.getChannel().lock();
不适合...? - 为什么我的问题只在切换回 Java-5 时才出现,而 Java-6 一切正常?