File Locking

As we saw in the threads chapter, sometimes you have two things going on at once in a program, and to keep them straight you may need to stop them from doing the same thing together. This situation can occur in file handling. An example would be a data file that several programs want to update at the same time. Let's say the last record in the file contains the total of all the other records in the file. When a program updates the file, it first writes the new data value, then it reads the current total, adjusts it for the new value, and writes it back. If another program should happen to come along at just the wrong time, both programs may read the old total, then they will both update it, but one update of the total will overwrite the other. Result: two data changes, but only one change to the total, so the file is now inaccurate.

One way to avoid this situation is to use threads and synchronize them on some suitable object. That only works when all the threads trying to update the file are running in one JVM. Many applications cannot accept that limitation, which is where file locking comes in. Using the new FileLock class introduced in JDK 1.4 as part of package java.nio, the programmer can lock part or all of a file for exclusive access.

As a reminder, a method called getChannel() has been added to each of the FileInputStream, FileOutputStream, and RandomAccessFile classes. Invoking the getChannel() method upon an instance of one of those classes will return a file channel connected to the underlying file.

Once you have the FileChannel object for an output file, you call its lock() or tryLock() method. Lock is a blocking call—it won't return until it has the lock, or the channel is closed, or the thread interrupted. The method tryLock() is not a blocking call. It returns at once, whether it got the lock or not. The return value from both these calls is a FileLock object or null. Both of these methods have variants that let you provide arguments to specify that a region of the file (rather than the whole thing) is locked. That allows finer control over how much different processes stay out of each others way, with consequently better performance.

Here is an example program that repeatedly tries to acquire a lock. When it gets the lock, it prints a message saying so, and sleeps for two seconds to simulate doing some work with the file. It then releases the lock. It sleeps a further third of a second and does the whole thing over again.

import java.io.*;
import java.nio.channels.*;
public class Lock {
    public static void main(String[] a) throws Exception {
       // Get a Channel for the file
       FileOutputStream fos = new FileOutputStream("data.txt");
       FileChannel fc = fos.getChannel();
       while (true) {
           // Try to get a lock
           FileLock lock = fc.tryLock();
           if (lock !=null) {
               System.out.println("got lock");
               Thread.sleep(2000);   // simulate some work
               lock.release();
           }
           Thread.sleep(333);
       }
    }
}

If you compile this lock program and run several different copies of it at the same time, you will see messages indicating that the locks have been acquired and released.

The file-locking API maps directly onto the native locking facility of the underlying operating system. Thus, the locks held on a file are visible to all programs that have access to the file, regardless of the language in which those programs are written.

Whether or not a lock actually physically prevents another program from accessing the content of the locked region is system-dependent and therefore unspecified. The native file-locking facilities of some systems are advisory, meaning that programs must cooperate to observe a known locking protocol in order to guarantee data integrity. On other systems native file locks are mandatory, meaning that if one program locks a region of a file, then all other programs are prevented from accessing that region in a way that would violate the lock. To ensure consistent and correct behavior across platforms, all programmers should treat the locks provided by this API as if they were advisory locks. Everyone should use the java.nio features to do file locking going forward.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.17.137