1

I am trying to implement cross process locking, I wanted only one jvm to run my piece of code. Does the following code breaks in any situation? If so how to make it unbreakable?

PS: The following code is taken from here and modified it according to my requirement.

public class TestMe
{
    public static void main(String args[]) throws InterruptedException
    {
        try
        {
            if (crossProcessLockAcquire())
            {
                // Success - This process now has the lock. 
                System.out.println("I am invincible");
                Thread.sleep(10000);
            }
            else
            {
                System.out.println("I am doomed");
            }
        }
        finally
        {
            crossProcessLockRelease(); // try/finally is very important.
        }
    }
    private static boolean crossProcessLockAcquire()
    {
        try
        {
            file = new File(System.getProperty("java.io.tmpdir") + File.separator + "file.lock");
            if (!file.exists())
            {
                file.createNewFile();
            }
            RandomAccessFile randomAccessFile = new RandomAccessFile(file,
                    "rw");
            FileChannel fileChannel = randomAccessFile.getChannel();
            fileLock = fileChannel.tryLock();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return fileLock == null ? false : true;
    }
    private static void crossProcessLockRelease()
    {
        if (fileLock != null)
        {
            try
            {
                fileLock.release();
                fileLock = null;
                if (file.exists())
                {
                    file.delete();
                }
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }
    private static FileLock fileLock = null;
    private static File file = null;
    static
    {
        Runtime.getRuntime().addShutdownHook(new Thread()
        {
            public void run()
            {
                crossProcessLockRelease();
            }
        });
    }
}
Community
  • 1
  • 1
Mahendran
  • 2,191
  • 5
  • 24
  • 40

1 Answers1

3

It can break here:

        file = new File(System.getProperty("java.io.tmpdir") + File.separator + "file.lock");
        if (!file.exists())
        {
            file.createNewFile();
        }

Between the time that you test for the existence of the file and the time that you create it, some other process might have created it.

Replace this with a directory and check for the return code of .mkdir() (it will fail if the directory already exists) since .mkdir() is atomic at the filesystem level:

file = new File("/path/to/sentinel");
if (!file.mkdir())
    someoneHasLocked();

And of course, .delete() on "unlock".

fge
  • 119,121
  • 33
  • 254
  • 329