我有一个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 http://docs.oracle.com/javase/1.5.0/docs/api/java/nio/channels/FileChannel.html#lock%28long,%20long,%20boolean%29其中提到:
文件锁代表整个 Java 虚拟机。它们不适合控制同一虚拟机内的多个线程对文件的访问。
那我做错了吗?如果是这样,正确的方法是什么?如果我做得对,为什么会陷入僵局?
Added:忘记提及 - 每个线程都拥有自己的该对象的副本,因此代码中不应存在任何同步问题。我感到可以安全地依赖FileChannel.lock()
确保写入不会交错的方法。
还添加了:我确实已经使用各种方法解决了这个问题synchronized
机制。然而,我确实有一些悬而未决的问题:
- Why is
FileLock lock = file.getChannel().lock();
不合适 ...?
- 为什么我的问题仅在切换回 Java-5 时出现,而 Java-6 一切正常?