我有一个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(); 不适合发布于 2012-07-18 15:20:48
FileLock只用于进程间锁定,javadoc读取:
文件锁代表整个Java虚拟机持有。它们不适合控制同一虚拟机中的多个线程对文件的访问。
要在java线程(同一个JVM)之间锁定,需要使用一些共享锁。我建议在文件编写类中使用同步块( 根据 to 这些 文章可能执行得最好):
final Object lock = new Object();
public void write(...){
synchronized(lock){
// do writing
}
}另一种方法是使用ReentrantLock,然后使用已证实的
final ReentrantLock lock = new ReentrantLock();
public void write(...){
try {
lock.lock()
// do the writing
} finally {
// forget this and you're screwed
lock.unlock();
}
}发布于 2012-07-18 14:44:11
您可能需要使用文件而不是hashmap在实际代码上实现关键部分概念。您可以创建一个同步块,也可以将文件访问代码分离为一个单独的过程,并使该方法同步。
实际上,一次只执行一个同步块。它给了你你所需要的独家访问权。
另一种方法是使用串行线程执行器,这取决于您的功能需求。
https://stackoverflow.com/questions/11543967
复制相似问题