+-
java内存映射文件多线程读/写
我有2个线程可以同时访问相同的大文件(.txt).

第一个线程正在从文件读取.
第二线程正在写入文件.

两个线程都访问相同的块,例如(start:0,blocksize:10),但使用不同的频道&缓冲实例

读者:

{
     int BLOCK_SIZE = 10;
     byte[] bytesArr = new byte[BLOCK_SIZE];
     File file = new File("/db.txt");
     RandomAccessFile randomFile = new RandomAccessFile(file, "r");
     FileChannel channel = randomFile.getChannel();
     MappedByteBuffer map = channel.map(FileChannel.MapMode.READ_ONLY, 0, BLOCK_SIZE);
     map.get(bytesArr , 0, BLOCK_SIZE);
     channel.close();
}

作家:

{
     int BLOCK_SIZE = 10;
     File file = new File("/db.txt");
     RandomAccessFile randomFile = new RandomAccessFile(file, "rw");
     FileChannel channel = randomFile.getChannel();
     MappedByteBuffer map = channel.map(FileChannel.MapMode.READ_WRITE, 0, BLOCK_SIZE);
     map.put(bytesToWrite);
     channel.close();
}

我知道,如果两者同时启动,我将获得重叠异常!但是我想知道什么,重叠到底在哪一点?我的意思是确切地说何时发生“锁定”?
示例:假设作者首先获得访问权限,然后如果读者尝试访问,那么在什么时候可以?

 FileChannel channel = randomFile.getChannel();
 // 1- can reader access here?
 MappedByteBuffer map = channel.map(FileChannel.MapMode.READ_WRITE, 0, BLOCK_SIZE);
 // 2- can reader access here?
 map.put(bytesToWrite);
 // 3- can reader access here?
 channel.close();
 // 4- can reader access here?

1 2 3 4

不能确定4,因为通道已关闭!那其他几点呢?

谢谢!

最佳答案
我正在总结与OP的聊天记录中的一些笔记. OP具有一个思维模型(就像我们大多数人一样),一旦线程将数据写入数据结构,该数据结构立即对所有其他线程可见.在使用内存映射文件的OP测试中,他已经确认在单插槽Intel CPU上确实如此.

不幸的是,事实并非如此,这是Java能够并且确实显示出硬件底层行为的领域. Java已被设计为假定代码是单线程的,因此可以如此进行优化,直到另行说明为止.这意味着因硬件和热点版本(以及热点收集的统计信息)而异.这种复杂性以及在单插槽Intel CPU上运行使OPs测试无效.

有关更多信息,以下链接将帮助您更深入地了解“ Java内存模型”.尤其是,同步并不仅仅意味着“互斥”.在硬件方面,它也涉及“数据可见性”和“指令排序”.单线程代码将两个主题视为理所当然.

> The Java Memory Model
> Double Checked Locking is Broken
> JSR 133

不用担心这会花费时间,而且一开始您会感到不知所措.一开始我们都觉得那样.当且仅当您遵循这一简单规则时,Java才能出色地隐藏这种复杂性.当线程读取或修改共享数据结构时,它必须在同步块内.即,写入线程和读取线程都可以.显然,我正在简化,但是遵循该规则,该程序将始终有效.仅当您对Java内存模型,内存障碍以及它与不同硬件的关系有非常深刻的了解时才打破它(即使如此,并发专家甚至也尽可能避免违反该规则;单线程通常要简单得多,并且可以是surprisingly fast ..为此,许多低延迟系统被设计为大多是单线程的.

直接回答OP的问题.问题中的示例代码没有锁定.没有内存障碍,没有并发控制.因此,读取和写入将如何交互的行为是不确定的.他们可能会工作,但可能不会.他们可能大部分时间都在工作.英特尔拥有所有CPU最高的内存保证,并且在单个插槽上运行测试案例英特尔CPU会遗漏许多复杂的错误.在Java 5和JSR 133出现之前,Sun也对此有所了解(有关详细信息,请阅读有关为何Java中破坏了Double Checked Locking的文章).

点击查看更多相关文章

转载注明原文:java内存映射文件多线程读/写 - 乐贴网