Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lock on existence of file in Java

Tags:

java

file

locking

Short version: Why should File.createNewFile() not be used for file locking? Or more specifically: Are there issues if it is used to lock an applications data directory?


Details:

I would like to protect my applications data directory using a lock file: If the file lock exists, the directory is locked and the application exits with an error message. If it does not exist it will be created and the application continues. On exit the file will be deleted.

The lock will not be created that often (i.e. performance is not an issue) and I have no problem with manually deleting the lock file in case of some error (i.e. failing to delete the file is not an issue).

The code looks something like this:

File lockFile = new File("lock");
boolean lockCreated = lockFile.createNewFile();
if (lockCreated)
{
    // do stuff
    lockFile.delete();
}
else
{
    System.err.println("Lockfile exists => please retry later");
    // alternative: Wait and retry e.g. 5 times
}

Now I'm a bit confused about the Javadoc of createNewFile():

Atomically creates a new, empty file named by this abstract pathname if and only if a file with this name does not yet exist. The check for the existence of the file and the creation of the file if it does not exist are a single operation that is atomic with respect to all other filesystem activities that might affect the file.

Note: this method should not be used for file-locking, as the resulting protocol cannot be made to work reliably. The FileLock facility should be used instead.

What are the potential problems mentioned in the note, considering the existence check and file creation are atomic?

This forum post from December 2007 indicates there are "significant platform differences" according to the Javadoc of File.delete() (although I cannot find such a statement since at least Java SE 1.4.2). But even if there would be such differences: Could they really cause the locking to fail (i.e. two processes think the data directory is usable at the same time)?


Note: I do not want any of the following:

  • Lock a file so that no other process can access and/or modify it (most information I found seems to discuss this issue).
  • Make sure no other process can remove the lock.
  • Synchronize multiple threads of the same JVM (although I think my solution should be able to handle that too).
like image 963
siegi Avatar asked Nov 10 '14 18:11

siegi


People also ask

How do you lock a file in Java?

File Locks in Java The Java NIO library enables locking files at the OS level. The lock() and tryLock() methods of a FileChannel are for that purpose. We can create a FileChannel through either a FileInputStream, a FileOutputStream, or a RandomAccessFile. All three have a getChannel() method that returns a FileChannel.

Does file exists lock the file?

No, File. Exist() only checks that the file in question is on the file system at the specified path. It does not access the file data or headers in anyway, so it won't put a lock on the file.

How do you create a file in Java if it does not exist?

Java creating file with FileThe File's createNewFile method creates a new, empty file named by the pathname if a file with this name does not yet exist. The createNewFile returns true if the named file does not exist and was successfully created; false if the named file already exists.

How do you check if a file is locked by another process in Java?

If the file is exclusively locked (by MS Word for example), there will be exception: java. io. FileNotFoundException: <fileName> (The process cannot access the file because it is being used by another process) . This way you do not need to open/close streams just for the check.


2 Answers

The Javadoc of Files.createFile(…), part of java.nio.file available since Java 7, repeats the promise of atomicity but does not mention anything about file based locking.


My reasoning:

  • Either the newer method (from java.nio.file.Files) is affected by the same (or similar) problems as the older one (from java.io.File) and the Javadoc is simply missing this information…
  • … or the newer method actually behaves more predictably and correct.

Given the error handling and specification in java.nio.file has generally been improved compared to the File class (existing ever since JDK 1.2), I assume the second alternative is correct.


My conclusion: Using Files.createFile(…) is fine for this use case.

like image 185
siegi Avatar answered Oct 21 '22 10:10

siegi


The short answer: reliable file based locking in Java is not practical.

The long answer: The issue with file based locking, in any OS, always comes down to what kind of storage system the file comes from. Almost all network accessed file systems (NFS, SAMBA, etc) have very unreliable (or at least unpredictable) synchronizations on file creates or deletes that make a general Java-ish approach inadvisable. In certain OSes, using local file systems, you can sometimes get what you desire. But you need to understand the underlying file system and its characteristics and proceed with care.

like image 43
Jay Guidos Avatar answered Oct 21 '22 09:10

Jay Guidos