Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to lock files on Linux using java.nio.channels.FileLock

I was creating an application in Java for which I want only one instance running. For this purpose I created a file and got a lock while my application is running.

I have following code which works on Windows, but failed on Linux: once I acquire a lock without unlocking it I can get another lock on it.

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;

public class MyApp {

private static File f;
private static FileChannel channel;
private static FileLock lock;

public static void main(String[] args) {
    try {
        f = new File("RingOnRequest.lock");
        // Check if the lock exist
        if (f.exists()) {
            // if exist try to delete it
            f.delete();
        }
        // Try to get the lock
        channel = new RandomAccessFile(f, "rw").getChannel();
        lock = channel.tryLock();
        if(lock == null)
        {
            // File is lock by other application
            channel.close();
            throw new RuntimeException("Only 1 instance of MyApp can run.");
        }
        // Add shutdown hook to release lock when application shutdown
        ShutdownHook shutdownHook = new ShutdownHook();
        Runtime.getRuntime().addShutdownHook(shutdownHook);

        //Your application tasks here..
        System.out.println("Running");
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
    catch(IOException e)
    {
        throw new RuntimeException("Could not start process.", e);
    }

}

public static void unlockFile() {
    // release and delete file lock
    try {
        if(lock != null) {
            lock.release();
            channel.close();
            f.delete();
        }
    } catch(IOException e) {
        e.printStackTrace();
    }
}

static class ShutdownHook extends Thread {

    public void run() {
        unlockFile();
    }
}

}
like image 335
kaysush Avatar asked Feb 21 '23 01:02

kaysush


1 Answers

You are deleting the lock file every time you run, so only one process can have a lock on it.

When you use FileLock, it is purely advisory—acquiring a lock on a file may not stop you from doing anything…reading, writing, and deleting a file may all be possible even when another process has acquired a lock. Sometimes, a lock might do more than this on a particular platform, but this behavior is unspecified, and relying on more than is guaranteed in the class documentation is a recipe for failure.

An "advisory lock" is only a signal that is visible to other processes that bother to look for it. If you depend on it for more than that, your program will break when run on some other platform.

Why would you delete the lock file anyway? The lock file is just like a boolean flag that is visible to every process on the system. Design your protocol to use it that way, and you'll have a reliable, cross platform locking mechanism.

like image 157
erickson Avatar answered Mar 05 '23 18:03

erickson