Java:线程安全的 RandomAccessFile

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2882168/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 23:16:21  来源:igfitidea点击:

Java: thread-safe RandomAccessFile

javamultithreadinglockingthread-safety

提问by Folkert van Heusden

After some serious googleing I found out that the RandomAccessFile-class is not thread-safe. Now I could use one semaphore to lock all reads and writes but I don't think that performs very well. In theory it should be possible to do multiple reads and one write at a time. How can I do this in Java? Is it possible at all?

经过一番认真的谷歌搜索后,我发现 RandomAccessFile 类不是线程安全的。现在我可以使用一个信号量来锁定所有读取和写入,但我认为这不是很好。理论上应该可以一次进行多次读取和一次写入。我怎样才能在 Java 中做到这一点?有可能吗?

Thanks!

谢谢!

采纳答案by DJClayworth

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.

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

回答by Kilian Foth

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.ReentrantReadWriteLockis what you are looking for.

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

回答by corsiKa

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;
        }
    }

}

回答by Stephen C

If a simple mutex on the entire file is going to give you a performance bottleneck, and RandomAccessFileis not thread-safe without a mutex, then you need to look at alternatives to RandomAccessFile.

如果整个文件上的简单互斥量会给您带来性能瓶颈,并且RandomAccessFile没有互斥量就不是线程安全的,那么您需要查看RandomAccessFile.

One alternative is to map the file into memory as a MappedBufferand use slices of the buffer to allow different threads to access the file without interfering with each other. Single writer / multiple reader locking at the granularity of the entire would be easy to implement. You could also go further and implement concurrent reading and writing of non-overlapping sections of the file, but that would be more complicated.

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

I would not be surprised to hear that someone, somewhere has already implemented this as a reusable library.

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