Использование блокировок файлов java в одной JVM и в нескольких JVM

Думаю, я что-то пропустил, но я не могу понять, как блокировки файлов работают в Java. Точнее - как это реализовано.

Кажется, я не могу получить (даже не могу попытаться получить) две или более блокировки для одного и того же файла внутри одной JVM. Первая блокировка будет успешно получена, все дальнейшие попытки получить больше блокировок приведут к исключению OverlapingFileLockException. Тем не менее это работает для отдельных процессов.

Я хочу реализовать хранилище данных, поддерживаемое файловой системой, которая предназначена для работы с несколькими одновременными запросами (как на чтение, так и на запись). Я хочу использовать блокировки файлов для блокировки определенных файлов в хранилище.

Похоже, мне нужно ввести еще одну синхронизацию (эксклюзивную) на уровне JVM и только потом синхронизировать файлы, чтобы избежать этого исключения.

Сделал кто-нибудь делает что-нибудь подобное?

Я подготовил простой тестовый пример, чтобы показать, в чем моя проблема. Я использую 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();
    }
}
5
задан Dead Programmer 19 April 2011 в 11:09
поделиться