gpt4 book ai didi

java内存映射文件多线程读/写

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:42:36 29 4
gpt4 key购买 nike

我有 2 个线程同时访问同一个大文件 (.txt)。

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

两个线程都访问同一个 block ,例如(开始:0, block 大小:10),但具有不同的 channel 和缓冲区实例

读者:

{
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();
}

我知道如果两者同时启动,我会得到 Overlapping Exceptions!但我想知道的是,重叠到底发生在哪一点?我的意思是什么时候发生“锁定”?示例:假设作者首先获得访问权限,然后如果读者尝试访问,那么此时可能吗?:

 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?

No 4 是肯定的,因为 channel 已经关闭了!其他点呢?

谢谢!

最佳答案

我从与 OP 的聊天对话中总结了一些笔记。 OP 有这样一种心理模型(就像我们大多数人一样),即一旦线程写入数据结构,该数据结构立即对所有其他线程可见。在使用内存映射文件的 OP 测试中,他已经确认这在单插槽 Intel CPU 上似乎是正确的。

不幸的是,这不是真的,这是 Java 可以并且确实显示硬件底层行为的领域。 Java 被设计为假设代码是单线程的,因此可以这样优化,直到它被告知不是这样。这意味着什么会因硬件和热点版本(以及热点收集的统计数据)而异。这种复杂性以及在单插槽英特尔 CPU 上运行使 OP 测试无效。

有关更多信息,以下链接将有助于更深入地了解“Java 内存模型”。特别是 synchronized 不仅仅意味着“互斥”;在硬件方面,它还与“数据可见性”和“指令排序”有关。单线程代码认为理所当然的两个主题。

如果这需要时间来消化,并且一开始您感到不知所措,请不要担心。一开始我们都有这种感觉。 Java 在隐藏这种复杂性方面做得非常出色,当且仅当您遵循这个简单的规则时。当线程读取或修改共享数据结构时,它必须在同步块(synchronized block)内。即写线程和读线程。显然我正在简化,但遵循该规则,程序将始终有效。仅当您对 Java 内存模型、内存障碍以及它与不同硬件的关系有非常深刻的理解时才打破它(即便如此,并发专家甚至会尽可能避免打破该规则;单线程通常要简单得多并且可以是 surprisingly fast .. 由于这个原因,许多低延迟系统主要设计为单线程)。


直接回答 OP 问题。问题中的示例代码没有锁定。没有内存障碍,根本没有并发控制。因此,读写交互的行为是不确定的。它们可能有效,也可能无效。他们可能大部分时间都在工作。英特尔拥有所有 CPU 中最强的内存保证,在单插槽英特尔 CPU 上运行测试用例会遗漏很多复杂的错误。在 Java 5 和 JSR 133 出现之前,Sun 也遇到了这个问题(阅读关于为什么 Double Checked Locking 在 Java 中被破坏的文章以获得更多详细信息)。

关于java内存映射文件多线程读/写,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31453114/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com