I have a write method that should safely write data to a file.
// 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!!"); } }
Now he has done a great job with me, although I know that he has wrinkles.
I recently changed a project that uses this code to build and run under Java 5 (from Java 6), and now it looks like it has come to a standstill, waiting for the file to lock. This is a multi-threaded application, and it is possible that several threads will try to write to a single file.
The debugger tells me that the hanging threads are waiting for the call to return FileLock lock = file.getChannel().lock() .
Some research has sparked this interesting little nugget that mentions:
File locks are stored on behalf of the entire Java virtual machine. They are not suitable for controlling access to a file by multiple threads on the same virtual machine.
So am I doing this wrong? If so, what is the right way? If I do it right, how did I get stuck?
Added: I forgot to mention - each thread has its own copy of this object, so there should not be any synchronization problems in the code. I felt confident in relying on the FileChannel.lock() method to ensure that entries do not alternate.
Added too: I really solved the problem using various synchronized mechanisms. However, I have unresolved questions:
- Why
FileLock lock = file.getChannel().lock(); not suitable ... ? - Why did my problems appear only when switching to Java-5, when everything worked perfectly with Java-6?
source share