java.nio.channels.FileLock Example
This article introduces the FileLock
class and its basic usage. This article examples show using file locks with FileChannel
s.
The examples in this article are compiled and run in Windows OS environment. Note that Java SE 7 is required to run the code.
1. Introduction
FileLock
is a token representing a lock on a region of a file. This is an abstract class defined in the java.nio.channels
package.
1.1. Creating a file lock
A file-lock object is created when a lock is acquired on a file via one of the lock()
or tryLock()
methods of the FileChannel
or AsynchronousFileChannel
classes.
A file-lock object is initially valid. It remains valid until the lock is released by invoking the release()
method, by closing the channel that was used to acquire it, or by the termination of the Java virtual machine, whichever comes first. The validity of a lock may be tested by invoking its isValid()
method.
1.2. Exclusive and shared locks
A file lock is either exclusive or shared.
- A shared lock prevents other concurrently-running programs from acquiring an overlapping exclusive lock, but does allow them to acquire overlapping shared locks.
- An exclusive lock prevents other programs from acquiring an overlapping lock of either type.
Whether a lock is exclusive or shared may be determined by invoking its isShared()
method.
1.3. Notes
- The locks held on a particular file by a single Java virtual machine do not overlap. The
overlaps()
method may be used to test whether a candidate lock range overlaps an existing lock. - File locks are held on behalf of the entire Java virtual machine. They are not suitable for controlling access to a file by multiple threads within the same virtual machine.
2. File Channels and Locking
The following FileChannel
class methods can be used to acquire a lock on an underlying file.
The lock()
methods return a FileLock
. An invocation of this method will block.
lock()
method acquires an exclusive lock on this channel’s file.lock(long position, long size, boolean shared)
method acquires a lock on the given region of this channel’s file. The lock may be an exclusive or of shared type.
The tryLock()
methods return a FileLock
or a null
if the lock could not be acquired because another program holds an overlapping lock. This method does not block.
tryLock()
method attempts to acquire an exclusive lock on this channel’s file.tryLock(long position, long size, boolean shared)
method attempts to acquires a lock on the given region of this channel’s file. The lock may be an exclusive or of shared type.
NOTE: See java.nio.channels.FileChannel Example for usage of file channels.
3. Examples
This examples show the usage of shared and exclusive locks in the following scenarios. File channels are used to access and lock the files.
- A shared lock allows concurrently-running programs to acquire overlapping shared locks.
- A shared lock prevents other concurrently-running programs from acquiring an overlapping exclusive lock.
- An exclusive lock prevents other programs from acquiring an overlapping exclusive lock.
- An exclusive lock prevents other programs from acquiring an overlapping shared lock.
NOTE: A data file is used in these example programs. All programs use the same file. It is to be created before running the code. The file is a text file named “examplefile.txt”. The contents (taken from the book One Hundred Years of Solitude by Gabriel Garcia Marquez) are as follows:
MANY YEARS LATER as he faced the firing squad, Colonel Aureliano Buendia was to remember that distant afternoon when his father took him to discover ice. At that time Macondo was a village of twenty adobe houses, built on the bank of a river of clear water that ran along a bed of polished stones, which were white and enormous, like prehistoric eggs.
4. Example 1
This example shows that a shared lock allows concurrently-running programs to acquire overlapping shared locks.
This example has two programs. Both programs read the same file through their respective file channels. The channels get a shared lock on the file.
The following code snippet shows the file channel acquiring the lock and verifying it.
FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.READ); FileLock lock = fileChannel.lock(0, Long.MAX_VALUE, true); System.out.println("Lock acquired: " + lock.isValid()); System.out.println("Lock is shared: " + lock.isShared());
The file channel is opened to read an existing file. The file channel’s lock()
method acquires a lock on the given region of this channel’s file. The lock()
method parameters:
0
is the position at which the locked region is to start; the begin of the file.Long.MAX_VALUE
specifies the size of the region to be locked; in this case the entire file.true
to request a shared lock.
The two methods of file lock isValid()
and isShared()
verify successful lock acquiring and if it is a shared lock respectively. At the end of the program the file channel’s close()
method closes the channel and this also releases the lock.
Running the example:
The code for both the programs is same. The programs are run concurrently in two different terminals. Note the input file with text content must be created before the program run.
4.1. The Code
FileLockSharedRead.java
import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.nio.file.Paths; import java.nio.file.Path; import java.nio.file.StandardOpenOption; public class FileLockSharedRead { public static void main (String [] args) throws IOException, InterruptedException { Path path = Paths.get("examplefile.txt"); FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.READ); System.out.println("File channel opened for read. Acquiring lock..."); FileLock lock = fileChannel.lock(0, Long.MAX_VALUE, true); System.out.println("Lock acquired: " + lock.isValid()); System.out.println("Lock is shared: " + lock.isShared()); ByteBuffer buffer = ByteBuffer.allocate(20); int noOfBytesRead = fileChannel.read(buffer); System.out.println("Buffer contents: "); while (noOfBytesRead != -1) { buffer.flip(); System.out.print(" "); while (buffer.hasRemaining()) { System.out.print((char) buffer.get()); } System.out.println(" "); buffer.clear(); Thread.sleep(1000); noOfBytesRead = fileChannel.read(buffer); } fileChannel.close(); // also releases the lock System.out.print("Closing the channel and releasing lock."); } }
4.2. The Output
File channel opened for read. Acquiring lock... Lock acquired: true Lock is shared: true Buffer contents: MANY YEARS LATER as he faced the firing squad, .... Closing the channel and releasing lock.
From the output:
- File channel opened for read. Acquiring lock…The file channel is open and ready to acquire the file lock.
- Lock acquired: true. The file lock is acquired.
- Lock is shared: true. The lock is of shared type.
- Buffer contents: This is the content from the file being read.
From the code run, note that both programs run concurrently without blocking. Note that the output is same for both the programs.
5. Example 2
This example shows that a shared lock prevents another concurrently-running program from acquiring an overlapping exclusive lock.
This example has two programs. Both the programs access the same file using file channels. The first program reads the file using a channel with a shared lock. The second program writes (appends) to the file using a channel with exclusive lock.
The following code snippet from FileLockSharedRead
program shows the file channel opened for read and acquiring the lock. Note the lock is of shared type.
FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.READ); FileLock lock = fileChannel.lock(0, Long.MAX_VALUE, true);
The following code snippet from FileLockExclusiveWrite
program shows the file channel opened for write and acquiring the lock. Note the lock is of exclusive type.
FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.WRITE, StandardOpenOption.APPEND); FileLock lock = fileChannel.lock();
The file channel’s lock()
method (without parameters) acquires an exclusive lock on this channel’s file. The lock is for the entire file.
Running the example:
The two programs are run concurrently in two different terminals. The FileLockSharedRead
is started first, and then the FileLockExclusiveWrite
. Observe that the program FileLockExclusiveWrite
waits until the FileLockSharedRead
releases the lock on the file.
Note the input file with text content must be created before the program run.
5.1. The Code
FileLockSharedRead.java
NOTE: The code for this program is shown in section 4. Example 1.
FileLockExclusiveWrite.java
import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.nio.file.Paths; import java.nio.file.Path; import java.nio.file.StandardOpenOption; public class FileLockExclusiveWrite { public static void main (String [] args) throws IOException { String input = "* end of file."; System.out.println("Input string: " + input); ByteBuffer buffer = ByteBuffer.wrap(input.getBytes()); String filePath = "examplefile.txt"; Path path = Paths.get(filePath); FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.WRITE, StandardOpenOption.APPEND); System.out.println("File channel opened for write. Acquiring lock..."); fileChannel.position(fileChannel.size() - 1); // positions at the end of file FileLock lock = fileChannel.lock(); // gets an exclusive lock System.out.println("Lock is shared: " + lock.isShared()); fileChannel.write(buffer); fileChannel.close(); // also releases lock System.out.println("Write complete. Closing the channel and releasing lock."); FilePrint.print(filePath); } }
NOTE: The line 31 in the above code uses a program FilePrint
to print the contents of a supplied text file. The program code is not shown here, but is included in the download ZIP file (see section 8. Download Java Source Code).
5.2. The Output
5.2.1. The FileLockSharedRead Output
File channel opened for read. Acquiring lock... Lock acquired: true Lock is shared: true Buffer contents: MANY YEARS LATER as he faced the firing squad, Colonel Aurel iano Buend.... Closing the channel and releasing lock.
From the output note that the file lock is shared.
5.2.2. The FileLockExclusiveWrite Output
Input string: * end of file. File channel opened for write. Acquiring lock... Lock is shared: false File contents: MANY YEARS LATER as he faced the firing squad, Colonel Aureliano Buendia ..., like prehistoric eggs. * end of file.
From the output:
- Input string: * end of file. This is the text to be written (appended) to the file.
- File channel opened for write. Acquiring lock…The file channel is open for write and ready to acquire the file lock.
- Lock is shared: false. The lock is not of shared type – it is exclusive.
- File contents: The output shows the file contents with the text written (appended). Note the string “* end of file.” appended at the end of the file.
From the code run, note that the FileLockExclusiveWrite
program waits until the FileLockSharedRead
completes/releases the lock.
6. Example 3
This example shows that an exclusive lock prevents another concurrently-running program from acquiring an overlapping exclusive lock.
This example has two programs. Both programs read the same file through their respective file channels. The channels get an exclusive lock on the file.
The following code snippet from FileLockExclusiveRead
program shows the file channel opened for read/write and acquiring the lock. Note the lock is of exclusive type.
FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.WRITE, StandardOpenOption.READ); FileLock lock = fileChannel.lock();
Running the program:
The code for both the programs is same. The programs are run concurrently in two different terminals. Note the input file with text content must be created before the program run.
6.1. The Code
FileLockExclusiveRead.java
import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.nio.file.Paths; import java.nio.file.Path; import java.nio.file.StandardOpenOption; public class FileLockExclusiveRead { public static void main (String [] args) throws IOException, InterruptedException { Path path = Paths.get("examplefile.txt"); FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.READ, StandardOpenOption.WRITE); System.out.println("File channel opened for read write. Acquiring lock..."); FileLock lock = fileChannel.lock(); // gets an exclusive lock System.out.println("Lock is shared: " + lock.isShared()); ByteBuffer buffer = ByteBuffer.allocate(20); int noOfBytesRead = fileChannel.read(buffer); System.out.println("Buffer contents: "); while (noOfBytesRead != -1) { buffer.flip(); System.out.print(" "); while (buffer.hasRemaining()) { System.out.print((char) buffer.get()); } System.out.println(" "); buffer.clear(); Thread.sleep(1000); noOfBytesRead = fileChannel.read(buffer); } fileChannel.close(); System.out.print("Closing the channel and releasing lock."); } }
6.2. The Output
File channel opened for read write. Acquiring lock... Lock is shared: false Buffer contents: MANY YEARS LATER as he faced the firing squad, .... Closing the channel and releasing lock.
From the output:
- File channel opened for read write. Acquiring lock…The file channel is open and ready to acquire the file lock.
- Lock is shared: false. The lock is of exclusive (not shared) type.
- Buffer contents: This is the contents from the file being read.
From the code run, note that the second FileLockExclusiveRead
program waits until the first program completes/releases the lock.
Note that the output is same for both the programs.
7. Example 4
This example shows that an exclusive lock prevents another concurrently-running program from acquiring an overlapping shared lock.
The example programs are FileLockExclusiveRead
and FileLockSharedRead
. These programs are already explained in previous examples 6. Example 3 and 4. Example 1 respectively.
Running the program:
The programs are run concurrently in two different terminals. The FileLockExclusiveRead
is started first, and then the FileLockSharedRead
. Note that the input file with text content must be created before the program run.
From the code run, note that the FileLockSharedRead
program waits until the FileLockExclusiveReadprogram
completes/releases the lock.
8. Download Java Source Code
This was an example of java.nio.channels.FileLock
You can download the full source code of this example here: FileLockExamples.zip
Hi Prasad Saya, thank you for your efforts to help people like me. I have Desktop app. written in javaFX. The user search a DB to produce a report that show in tableView. I want to export that table to excel file. Everything work fine. The only issue I have is when the file is created and try to open it, there is a message telling the file is Locked by another user for editing, which is the app that created the file. When I close the app the file open without getting that message. How do I release the… Read more »