Java: thread-safe RandomAccessFile Java: thread-safe RandomAccessFile multithreading multithreading

Java: thread-safe RandomAccessFile


I could use one semaphore to lock all reads and writes but I don't think that performs very well.

With respect to performance, NEVER think. ALWAYS measure.

That said, java.util.concurrent.locks.ReentrantReadWriteLock is what you are looking for.


Partial locking of a file is a complex business which a lot of operating systems avoid doing. However if you insist on doing it, one way is to design your own locking mechanism object that records which parts of the file are locked. Essentially before reading or writing an object must request a lock for a specific byte range of the file. Locks are considered to clash if they overlap at all in byte range. Read and write locks are treated differently: a read can overlap with any number of read locks safely, but a write lock must overlap with no other locks, read or write. There are a lot of questions about whether to wait or abort if you can't get the lock, and whether to block reads while a write is waiting, but only you can answer them about your application.

Given the complexity of this it may be better to lock the entire file. Check to see if you get adequate performance - and don't forget you can allow multiple reads at once, as long as there are no writes.


Consider this approach - it allows unlimited readers, and when a writer wants to write, it waits for current readers to finish to do its write.

class readWriteSemaphore() {    private Object lock;    List<Thread> readers;    Thread writer;    readWriteSemaphore() {        readers = new LinkedList<Thread>(); // Linked list is inefficient for many threads, FYI        writer = null;    }    /**    * Returns true if and only if you have acquired a read    * maybe use while(!rws.acquireRead(Thread.currentThread())) Thread.sleep(50); // or something    */    boolean acquireRead(Thread t) {        synchronized(lock) {            if(writer == null) {                readers.add(t);                return true;            }            return false; // yes this could go outside the synch block... oh well        }    }    void releaseRead(Thread t) {        synchronized(lock) {            while(readers.remove(t)); // remove this thread completely        }    }    boolean acquireWrite(Thread t) {        synchronized(lock) {            if(writer == null) return false;            writer = t;        }        while(readers.size() > 0) Thread.sleep(50); // give readers time to finish.         //They can't re-enter yet because we set the writer,        // if you attempt to acquire a write, future reads will be false until you're done        return true;    }    void releaseWrite(Thread t) {        synchronized(lock) {            if(t != writer) throw new IllegalArgumentException("Only writer can release itself");            writer = null;        }    }}