How to lock a file

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?
+4
source share
2 answers

FileLock is only for locking between processes, javadoc :

"File locks are stored on behalf of the entire Java virtual machine. They are not suitable for controlling file access for multiple threads within the same virtual machine ."

To lock between java threads (the same JVM) you need to use some common lock. I would suggest using a synchronized block in the file recording class (which , according to these articles , will most likely work best):

 final Object lock = new Object(); public void write(...){ synchronized(lock){ // do writing } } 

Another approach is to use ReentrantLock and then use a proven idiom

 final ReentrantLock lock = new ReentrantLock(); public void write(...){ try { lock.lock() // do the writing } finally { // forget this and you're screwed lock.unlock(); } } 
+2
source

You may need to implement the critical section concept for the actual code using this file, not a hash map. You can create a synchronized block or split the file access code into a separate procedure and synchronize this method.

Essentially, only one thread executes a synchronized block at a time. This gives you the exclusive access you need.

Another way to do this is to use a serial Executor thread, depending on your functional requirements.

You can look at this topic: How to synchronize access to files in a shared folder using Java (OR: ReadWriteLock at the network level)

+1
source

All Articles