Java mmap MappedByteBuffer
Java mmap MappedByteBuffer
假设我已经映射了一个内存区域 [0, 1000],现在我有了 MappedByteBuffer。
我可以同时从多个线程读取和写入此缓冲区而不锁定吗,假设每个线程访问缓冲区的不同部分以获取 exp。 T1 [0, 500], T2 [500, 1000]?
如果以上为真,是否可以确定是为多个线程创建一个大缓冲区更好,还是为每个线程创建更小的缓冲区?
详细介绍:
如果您想自己学习如何回答这些问题,请查看它们的实现源代码:
- MappedByteBuffer: https://github.com/himnay/java7-sourcecode/blob/master/java/nio/MappedByteBuffer.java(注意它仍然是抽象,所以你不能直接实例化它)
- 扩展 ByteBuffer:https://github.com/himnay/java7-sourcecode/blob/master/java/nio/ByteBuffer.java
- 扩展缓冲区:https://github.com/himnay/java7-sourcecode/blob/329bbb33cbe8620aee3cee533eec346b4b56facd/java/nio/Buffer.java(仅进行索引检查,不授予对任何缓冲区内存的实际访问权限)
现在有点复杂了:
当你想分配一个 MappedByteBuffer 时,你会得到一个
- 堆字节缓冲区:https://github.com/himnay/java7-sourcecode/blob/329bbb33cbe8620aee3cee533eec346b4b56facd/java/nio/HeapByteBuffer.java
- 或 DirectByteBuffer:https://github.com/himnay/java7-sourcecode/blob/329bbb33cbe8620aee3cee533eec346b4b56facd/java/nio/DirectByteBuffer.java
无需浏览网页,您还可以简单地下载您的 Java 版本的源代码包并将它们附加到您的 IDE 中,这样您就可以看到开发和调试中的代码模式。容易多了。
简短(不完整)答案:
它们都不能防止多线程。
- 因此,如果您需要调整 MappedByteBuffer 的大小,您可能会变得陈旧甚至糟糕(ArrayIndexOutOfBoundsException)访问
- 如果大小不变,就您的要求而言,您可以依靠任一实现来实现“线程安全”
旁注,这里还有 Java 实现中的一个实现失败蔓延:
- MappedByteBuffer 扩展了 ByteBuffer
- ByteBuffer 有堆
byte[]
称为“hb”
- DirectByteBuffer 扩展 MappedByteBuffer 扩展 ByteBuffer
- 所以DirectByteBuffer还有ByteBuffer的
byte[] hb
缓冲区,
-
- 但不使用它
-
- 而是创建和管理自己的缓冲区
这个设计缺陷来自那些 类 的逐步开发(它们不是同时计划和实施的),以及包可见性的主题,导致 类 的反转=143=] 的实施。
现在是真正的答案:
如果你想进行适当的面向对象编程,除非绝对需要,否则你不应该共享资源。
这特别意味着每个线程都应该有自己的缓冲区。
拥有一个全局缓冲区的优点:唯一的“优点”是减少额外对象引用的额外内存消耗。但这种影响是 SO MINIMAL(甚至 1:10000 应用程序 RAM 消耗的变化都没有),您永远不会注意到它。由于各种奇怪的 (Java) 原因,到处都有如此多的其他对象分配,这是您最不关心的 。另外,您将不得不引入额外的数据(索引边界),这会进一步减少 'advantage'。
拥有独立缓冲区的巨大优势:
- 您将永远不必关心 pointer/index 算术
-
- 尤其是在任何给定时间需要更多线程的情况下
- 您可以随时自由分配新线程,而无需重新排列任何数据或进行更多指针运算
- 您可以在需要时自由 reallocate/resize 每个单独的缓冲区(无需担心所有其他线程的索引要求)
- 调试:您可以更轻松地定位由“越界写入”导致的问题,因为如果他们尝试,坏线程就会崩溃,而不是其他必须处理损坏数据的线程
-
- Java 总是在访问数组之前检查每个数组访问(在像
byte[]
这样的普通堆数组上),以防止副作用
-
- 回想一下:曾几何时,操作系统引入了线性地址space,因此程序不必关心地址的位置他们加载的硬件 RAM。
-
- 您的单缓冲区设计将是倒退的一步。
结论:
如果你想要一个非常糟糕的设计选择 - 这会让以后的生活变得更加艰难 - 你可以选择 一个全局缓冲区 。
如果您想以正确的 OO 方式进行操作,请将这些缓冲区分开。没有复杂的依赖关系和副作用问题。
假设我已经映射了一个内存区域 [0, 1000],现在我有了 MappedByteBuffer。
我可以同时从多个线程读取和写入此缓冲区而不锁定吗,假设每个线程访问缓冲区的不同部分以获取 exp。 T1 [0, 500], T2 [500, 1000]?
如果以上为真,是否可以确定是为多个线程创建一个大缓冲区更好,还是为每个线程创建更小的缓冲区?
详细介绍:
如果您想自己学习如何回答这些问题,请查看它们的实现源代码:
- MappedByteBuffer: https://github.com/himnay/java7-sourcecode/blob/master/java/nio/MappedByteBuffer.java(注意它仍然是抽象,所以你不能直接实例化它)
- 扩展 ByteBuffer:https://github.com/himnay/java7-sourcecode/blob/master/java/nio/ByteBuffer.java
- 扩展缓冲区:https://github.com/himnay/java7-sourcecode/blob/329bbb33cbe8620aee3cee533eec346b4b56facd/java/nio/Buffer.java(仅进行索引检查,不授予对任何缓冲区内存的实际访问权限)
现在有点复杂了:
当你想分配一个 MappedByteBuffer 时,你会得到一个
- 堆字节缓冲区:https://github.com/himnay/java7-sourcecode/blob/329bbb33cbe8620aee3cee533eec346b4b56facd/java/nio/HeapByteBuffer.java
- 或 DirectByteBuffer:https://github.com/himnay/java7-sourcecode/blob/329bbb33cbe8620aee3cee533eec346b4b56facd/java/nio/DirectByteBuffer.java
无需浏览网页,您还可以简单地下载您的 Java 版本的源代码包并将它们附加到您的 IDE 中,这样您就可以看到开发和调试中的代码模式。容易多了。
简短(不完整)答案:
它们都不能防止多线程。
- 因此,如果您需要调整 MappedByteBuffer 的大小,您可能会变得陈旧甚至糟糕(ArrayIndexOutOfBoundsException)访问
- 如果大小不变,就您的要求而言,您可以依靠任一实现来实现“线程安全”
旁注,这里还有 Java 实现中的一个实现失败蔓延:
- MappedByteBuffer 扩展了 ByteBuffer
- ByteBuffer 有堆
byte[]
称为“hb” - DirectByteBuffer 扩展 MappedByteBuffer 扩展 ByteBuffer
- 所以DirectByteBuffer还有ByteBuffer的
byte[] hb
缓冲区, -
- 但不使用它
-
- 而是创建和管理自己的缓冲区
这个设计缺陷来自那些 类 的逐步开发(它们不是同时计划和实施的),以及包可见性的主题,导致 类 的反转=143=] 的实施。
现在是真正的答案:
如果你想进行适当的面向对象编程,除非绝对需要,否则你不应该共享资源。 这特别意味着每个线程都应该有自己的缓冲区。
拥有一个全局缓冲区的优点:唯一的“优点”是减少额外对象引用的额外内存消耗。但这种影响是 SO MINIMAL(甚至 1:10000 应用程序 RAM 消耗的变化都没有),您永远不会注意到它。由于各种奇怪的 (Java) 原因,到处都有如此多的其他对象分配,这是您最不关心的 。另外,您将不得不引入额外的数据(索引边界),这会进一步减少 'advantage'。
拥有独立缓冲区的巨大优势:
- 您将永远不必关心 pointer/index 算术
-
- 尤其是在任何给定时间需要更多线程的情况下
- 您可以随时自由分配新线程,而无需重新排列任何数据或进行更多指针运算
- 您可以在需要时自由 reallocate/resize 每个单独的缓冲区(无需担心所有其他线程的索引要求)
- 调试:您可以更轻松地定位由“越界写入”导致的问题,因为如果他们尝试,坏线程就会崩溃,而不是其他必须处理损坏数据的线程
-
- Java 总是在访问数组之前检查每个数组访问(在像
byte[]
这样的普通堆数组上),以防止副作用
- Java 总是在访问数组之前检查每个数组访问(在像
-
- 回想一下:曾几何时,操作系统引入了线性地址space,因此程序不必关心地址的位置他们加载的硬件 RAM。
-
- 您的单缓冲区设计将是倒退的一步。
结论:
如果你想要一个非常糟糕的设计选择 - 这会让以后的生活变得更加艰难 - 你可以选择 一个全局缓冲区 。
如果您想以正确的 OO 方式进行操作,请将这些缓冲区分开。没有复杂的依赖关系和副作用问题。