
第一个线程正在从文件读取.
第二线程正在写入文件.
两个线程都访问相同的块,例如(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,因为通道已关闭!那其他几点呢?
谢谢!
不幸的是,事实并非如此,这是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内存映射文件多线程读/写 - 乐贴网