Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using java file locks within single JVM and across multiple JVMs

I guess I miss something, but I cannot understand how file locks work in Java. To be more exact - how it is implemented.

It seems I cannot acquire (even cannot attempt acquiring) two or more locks for the same file inside single JVM. First lock will be successfully acquired, all further attempts to acquire more locks will result in OverlapingFileLockException. Nevertheless it works for separate processes.

I want to implement data-storage backed by file-system which is intended to work with multiple concurrent requests (both read and write). I want to use file locks to lock on particular files in the storage.

It seems that I have to introduce one more synchronization (exclusive) on JVM-level and only then sync on files to avoid this exception.

Did anyone do anything like that?

I prepared simple test case to show what my problem is. I use Mac OS X, Java 6.

import junit.framework.*;

import javax.swing.*;
import java.io.*;
import java.nio.channels.*;

/**
 * Java file locks test.
 */
public class FileLocksTest extends TestCase {
    /** File path (on Windows file will be created under the root directory of the current drive). */
    private static final String LOCK_FILE_PATH = "/test-java-file-lock-tmp.bin";

    /**
     * @throws Exception If failed.
     */
    public void testWriteLocks() throws Exception {
        final File file = new File(LOCK_FILE_PATH);

        file.createNewFile();

        RandomAccessFile raf = new RandomAccessFile(file, "rw");

        System.out.println("Getting lock...");

        FileLock lock = raf.getChannel().lock();

        System.out.println("Obtained lock: " + lock);

        Thread thread = new Thread(new Runnable() {
            @Override public void run() {
                try {
                    RandomAccessFile raf = new RandomAccessFile(file, "rw");

                    System.out.println("Getting lock (parallel thread)...");

                    FileLock lock = raf.getChannel().lock();

                    System.out.println("Obtained lock (parallel tread): " + lock);

                    lock.release();
                }
                catch (Throwable e) {
                    e.printStackTrace();
                }
            }
        });

        thread.start();

        JOptionPane.showMessageDialog(null, "Press OK to release lock.");

        lock.release();

        thread.join();
    }

    /**
     * @throws Exception If failed.
     */
    public void testReadLocks() throws Exception {
        final File file = new File(LOCK_FILE_PATH);

        file.createNewFile();

        RandomAccessFile raf = new RandomAccessFile(file, "r");

        System.out.println("Getting lock...");

        FileLock lock = raf.getChannel().lock(0, Long.MAX_VALUE, true);

        System.out.println("Obtained lock: " + lock);

        Thread thread = new Thread(new Runnable() {
            @Override public void run() {
                try {
                    RandomAccessFile raf = new RandomAccessFile(file, "r");

                    System.out.println("Getting lock (parallel thread)...");

                    FileLock lock = raf.getChannel().lock(0, Long.MAX_VALUE, true);

                    System.out.println("Obtained lock (parallel thread): " + lock);

                    lock.release();

                }
                catch (Throwable e) {
                    e.printStackTrace();
                }
            }
        });

        thread.start();

        JOptionPane.showMessageDialog(null, "Press OK to release lock.");

        lock.release();

        thread.join();
    }
}
like image 302
Yakov Avatar asked Apr 19 '11 11:04

Yakov


People also ask

Can we have 2 jvm in single machine?

Yes, you can run multiple JVM's on a single machine. Sun packages the tools to run the jvm in a few different ways. Usually, you either have a java development kit (jdk) or java standard edition (jse) installed as the default.

What is file locking in Java?

A token representing a lock on a region of a file. A file-lock object is created each time a lock is acquired on a file via one of the lock or tryLock methods of the FileChannel class, or the lock or tryLock methods of the AsynchronousFileChannel class. A file-lock object is initially valid.

Can we have multiple jvm?

Yes,you can install more than one jvm in your PC, because OS loads an instance of jvm (not whole jvm) in RAM. We can call different jvm like JDK 1.4 or JDK 1.6 by setting its path. Multiple JRE (Java Runtime Enviroment) is very possible. Multiple number of JVMs can run on a single machine.


2 Answers

From the Javadoc:

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.

like image 136
user207421 Avatar answered Nov 14 '22 22:11

user207421


You can only acquire a lock once per file. Locks are not re-entrant AFAIK.

IMHO: Using files to communicate between process is a very bad idea. Perhaps you will be able to get this to work reliably, let me know if you can ;)

I would have one and only one thread read/write in only one process.

like image 27
Peter Lawrey Avatar answered Nov 14 '22 23:11

Peter Lawrey