Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

File lock between threads and processes

I'm writing a program that writes to a single file from both different threads on the same JVM and from different JVM's/processes. Is there a way to lock a file for both threads and processes, so that no matter how many threads/processes are trying to write at the same time, only 1 can write at a time?

Currently I have something similar to the following which works for locking threads, but not for blocking processes. If I try using FileLock on top of the implementation below it appears the synchronized stops working.

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import scripts.com.adz.commons.utils.FileUtilities;

import java.io.*;

public class Foo {
    public static void main(String[] args) throws IOException {
        Bar bar = new Bar();
        bar.start();

        while (true) {
            FileUtilities.writeObjectToFile("C:\\test.html", "foo");
        }
    }
}

class Bar extends Thread {
    @Override
    public void run() {
        while (true) {
            try {
                FileUtilities.writeObjectToFile("C:\\test.html", "bar");
            } catch (IOException ignored) {}
        }
    }
}

class FileUtilitiess {
    private static final Object _lock = new Object();

    public static <T> T readObjectFromFile(File file) throws IOException, ClassNotFoundException {
        synchronized (_lock) {
            final byte[] bytes = FileUtils.readFileToByteArray(file);

            ByteArrayInputStream bis = null;
            ObjectInputStream ois = null;

            try {
                ois = new ObjectInputStream(bis = new ByteArrayInputStream(bytes));

                return (T) ois.readObject();
            } finally {
                IOUtils.closeQuietly(ois);
                IOUtils.closeQuietly(bis);
            }
        }
    }

    public static void writeObjectToFile(File file, Object object) throws IOException {
        System.out.println("Sent object: " + object.toString());
        synchronized (_lock) {
            System.out.println("Writing object: " + object.toString());

            ByteArrayOutputStream bos = null;
            ObjectOutputStream oos = null;

            try {
                oos = new ObjectOutputStream(bos = new ByteArrayOutputStream());
                oos.writeObject(object);

                FileUtils.writeByteArrayToFile(file, bos.toByteArray());

                // - Start: For testing lock.
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException ignored) {}
                // - End: For testing lock.
            } finally {
                IOUtils.closeQuietly(oos);
                IOUtils.closeQuietly(bos);
            }
        }
    }
}
like image 852
Adam Rivers Avatar asked Oct 19 '22 18:10

Adam Rivers


1 Answers

See FileLock javadoc:

File locks are held on behalf of the entire Java virtual machine.

That means that on the OS level different threads of your application will have the same right to access the locked region.

To lock the file access from different threads you have to encapsulate your file IO code and to enforce synchronized execution.

like image 144
Jeor Mattan Avatar answered Oct 29 '22 01:10

Jeor Mattan