AFAIK,Java中的内存基于堆,内存从堆中动态分配给对象,并且没有共享内存的概念。
如果没有共享内存的概念,那么Java程序之间的通信应该是耗时的。在 C 中,与其他通信模式相比,通过共享内存进行进程间通信更快。
如我错了请纠正我。另外,2 个 Java progs 相互交谈的最快方式是什么。
由于没有官方 API 来创建共享内存段,因此您需要借助辅助库/DDL 和 JNI 来使用共享内存让两个 Java 进程相互通信。
实际上,这很少成为问题,因为 Java 支持线程,因此您可以在同一个 Java VM 中运行两个“程序”。这些将共享同一个堆,因此通信将是即时的。另外,您不会因为共享内存段的问题而出错。
Java Chronicle值得一看;Chronicle-Queue和Chronicle-Map都使用共享内存。
这些是我不久前做过的一些测试,比较了各种堆外和堆上选项。
要看的一件事是使用内存映射文件,使用Java NIO 的 FileChannel类或类似的(参见 map() 方法)。我们已经非常成功地使用它在同一台机器上的 Java 进程和 C 本机进程之间进行通信(在我们的例子中是单向的)。
我承认我不是文件系统专家(幸运的是,我们确实有一个工作人员!)但是我们的性能绝对是非常快的——实际上你将页面缓存的一部分当作一个文件并读取 + 写入它直接没有系统调用的开销。我不确定保证和一致性——Java中有一些方法可以强制将更改写入文件,这意味着它们(有时?通常?通常?通常?不确定)写入实际的底层文件(有点?非常?非常?) lazily,这意味着在某些情况下它基本上只是一个共享内存段。
理论上,据我了解,内存映射文件实际上可以由共享内存段支持(我认为它们只是文件句柄),但我不知道在没有 JNI 的情况下在 Java 中这样做的方法。
共享内存有时很快。有时它不是——它会损害 CPU 缓存,并且同步通常是一种痛苦(如果它依赖于互斥锁等,可能是主要的性能损失)。
Barrelfish是一个操作系统,它表明随着内核数量的增加,使用消息传递的 IPC 实际上比共享内存更快(在传统的 X86 架构以及你猜它所针对的更奇特的 NUMA NUCA 东西上)。
因此,您对共享内存快速的假设需要针对您的特定场景和目标硬件进行测试。如今,这不是一个通用的合理假设!
我能想到几种类似的技术:
不幸的是,两者都没有共享内存的正确速度,但它们确实处理了并发访问等问题。
最简单的方法是让两个进程实例化同一个内存映射文件。实际上,它们将共享相同的堆外内存空间。您可以获取此内存的物理地址并用于sun.misc.Unsafe
写入/读取原语。它通过 putXXXVolatile/getXXXVolatile 方法支持并发。看看CoralQueue,它可以轻松提供 IPC 以及同一 JVM 内的线程间通信。
免责声明:我是 CoralQueue 的开发者之一。
与 Peter Lawrey 的 Java Chronicle 类似,您可以尝试Jocket。
它还使用 MappedByteBuffer 但不保留任何数据,旨在用作 Socket / ServerSocket 的替代品。
1kB 乒乓球的往返延迟约为半微秒。
MappedBus ( http://github.com/caplogic/mappedbus ) 是我在 github 上添加的一个库,它通过消息传递在多个(两个以上)Java 进程/JVM 之间启用 IPC。
传输可以是内存映射文件或共享内存。要将它与共享内存一起使用,只需遵循 github 页面上的示例,但将读取器/写入器指向“/dev/shm/”下的文件。
它是开源的,实现在 github 页面上有完整的解释。
考恩提供的信息是正确的。然而,即使是共享内存在多个线程(和/或进程)中也不总是相同的。关键的根本原因是 Java 内存模型(它建立在硬件内存模型之上)。请参阅多个线程能否看到 Java 中直接映射的 ByteBuffer 上的写入?对这个主题进行非常有用的讨论。