Java:线程安全的RandomAccessFile

经过一些严肃的googleing后,我发现RandomAccessFile-class不是线程安全的。 现在我可以使用一个信号量锁定所有读写但我不认为它表现得非常好。 理论上,应该可以一次执行多次读取和一次写入。 我怎么能用Java做到这一点? 有可能吗?

谢谢!

部分锁定文件是一项复杂的业务,许多操作系统都避免这样做。 但是,如果您坚持这样做,一种方法是设计自己的锁定机制对象,记录文件的哪些部分被锁定。 基本上在读取或写入对象之前,必须请求锁定文件的特定字节范围。 如果锁在字节范围内完全重叠,则认为它们发生冲突。 读写锁的处理方式不同:读取可以安全地与任意数量的读锁重叠,但写锁必须与其他锁,读或写重叠。 如果你无法获得锁定,是否要等待或中止,以及在写入等待时是否阻止读取,有很多问题,但只有你可以回答它们关于你的应用程序。

鉴于其复杂性,锁定整个文件可能更好。 检查您是否获得足够的性能 – 并且不要忘记您可以一次允许多次读取,只要没有写入。

我可以使用一个信号量来锁定所有的读写操作,但我不认为它表现得非常好。

关于性能,永远不要想。 总是衡量。

也就是说, java.util.concurrent.locks.ReentrantReadWriteLock就是你要找的。

考虑这种方法 – 它允许无限的读者,当作家想要写作时,它等待当前读者完成写作。

 class readWriteSemaphore() { private Object lock; List readers; Thread writer; readWriteSemaphore() { readers = new LinkedList(); // 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; } } } 

如果整个文件上的一个简单的互斥锁会给你带来性能瓶颈,而且没有互斥锁,则RandomAccessFile不是线程安全的,那么你需要查看RandomAccessFile替代方法。

一种替代方法是将文件作为MappedBuffer映射到内存中,并使用缓冲区的片段允许不同的线程访问文件而不会相互干扰。 单个编写器/多个读取器锁定在整个粒度将是易于实现。 您还可以进一步实现并发读取和写入文件的非重叠部分,但这会更复杂。

听到某个人已经将其作为可重用的库实现,我不会感到惊讶。