The Java NIO (New I/O) API introduced in JDK 1.4 not only provides many advanced features which were not available in Java I/O API but also a better way of performing I/O. One such feature provided by NIO is an ability to lock file on the operating system level.
While reading or updating a file in Java, you need to ensure that it is not being used by other processes to avoid the possibility of lost updates or using stale data. The Java NIO API enables locking of the file at the operating system level so that other processes cannot access the file.
The Java NIO API allows obtaining shared or exclusive lock on either the entire file or a part of the file. The FileChannel
provides two lock()
methods for this purpose. The lock()
method obtains an exclusive lock on the entire file whereas lock(long position, long size, boolean shared)
method can be used to obtain shared or exclusive lock on a region of file. These methods of FileChannel
will block until the lock is obtained. The non-blocking equivalent methods tryLock()
and tryLock(long position, long size, boolean shared)
are also available. All these methods will lock the file (or attempt to lock in case of tryLock
) and will return the FileLock
object, if the file is locked. The tryLock
returns null if the file is not locked.
The getChannel()
method is available for many byte stream and character stream classes of Java I/O API to obtain the FileChannel
.
The FileLock
instance represents a lock on the file or a region of the file. The file lock is obtained by the FileChannel
until the lock on the file is released or the channel is closed or the JVM is terminated. The release()
method of FileLock
is called to release a file lock. As a good practice, it is usually called inside the finally block to ensure that it is always called unless there is an abnormal termination of JVM.
There are certain platform dependencies in locking files. Though, the shared lock is specified, some operating systems may allow obtaining only exclusive locks. Overlapping of shared locks is allowed but a shared lock cannot overlap an exclusive lock. Any type of lock cannot overlap an exclusive lock. A file lock cannot be overlapped within the same JVM. FileLock
is a thread-safe class. Whether advisory or mandatory locks are obtained on a file depends on the underlying operating system.
In Java 7, the FileChannel
implements the java.lang.AutoCloseable
interface, which means that when used inside try-with-resources, there is no need to explicitly close the FileChannel
.
The Listing 1. demonstrates locking a file before writing and releasing the lock after write.
RandomAccessFile file = new RandomAccessFile(“filename”,“rw”); try(FileChannel fileChannel = file.getChannel()) { ByteBuffer buffer = ByteBuffer.allocate(100); String stringToBeCopied = “This text is written in file”; buffer.write(stringToBeCopied.getBytes()); FileLock lock = null; //obtain exclusive lock on the file for writing try { lock = fileChannel.lock(); fileChannel.put(buffer); } finally { if(lock != null) { lock.release(); } } }
Listing 1. Locking the file before writing