Java mmap MappedByteBuffer

Java mmap MappedByteBuffer

假设我已经映射了一个内存区域 [0, 1000],现在我有了 MappedByteBuffer。

我可以同时从多个线程读取和写入此缓冲区而不锁定吗,假设每个线程访问缓冲区的不同部分以获取 exp。 T1 [0, 500], T2 [500, 1000]?

如果以上为真,是否可以确定是为多个线程创建一个大缓冲区更好,还是为每个线程创建更小的缓冲区?

详细介绍:

如果您想自己学习如何回答这些问题,请查看它们的实现源代码:

现在有点复杂了:

当你想分配一个 MappedByteBuffer 时,你会得到一个

无需浏览网页,您还可以简单地下载您的 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 方式进行操作,请将这些缓冲区分开。没有复杂的依赖关系和副作用问题。