Java中共享内存的任何概念

AFAIK,Java中的内存基于堆,内存从中动态分配给对象,并且没有共享内存的概念。

如果没有共享内存的概念,那么Java程序之间的通信应该是耗时的。 在C中,与其他通信模式相比,通过共享存储器进行进程间通信更快。

如我错了请纠正我。 另外,两个Java程序相互交流的最快方式是什么。

由于没有用于创建共享内存段的官方API,因此需要使用帮助程序库/ DDL和JNI来使用共享内存来使两个Java进程相互通信。

实际上,由于Java支持线程,因此这很少成为问题,因此您可以在同一个Java VM中运行两个“程序”。 那些将共享相同的堆,因此通信将是即时的。 另外,由于共享内存段的问题,您无法获得错误。

至少有两种方法 – RAM驱动器或Apache APR 。

这里和这里的细节与一些性能测量。

Peter Lawrey的Java Chronicle项目值得关注。

这些是我之前做过的一些测试 ,比较了各种堆外和堆上选项。

共享内存有时很快。 有时它不是 – 它会伤害CPU缓存和同步通常是一种痛苦(并且它应该依赖于互斥体等,这可能是一个主要的性能损失)。

Barrelfish是一个操作系统,它表明使用消息传递的IPC实际上比共享内存更快,因为核心数量增加(在传统的X86架构上以及你认为它所针对的更具异国情调的NUMA NUCA东西)。

因此,您对共享内存快速的假设需要针对您的特定方案和目标硬件进行测试。 这些天它不是一般的声音假设!

要注意的一件事是使用内存映射文件 ,使用Java NIO的FileChannel类或类似文件(请参阅map()方法)。 我们非常成功地使用它来在同一台机器上的Java进程和C本机进程之间进行通信(在我们的例子中是单向的)。

我承认我不是文件系统专家(幸运的是我们有一个人员!)但我们的性能绝对超快 – 实际上你将页面缓存的一部分视为文件并阅读+写入直接没有系统调用的开销。 我不确定保证和一致性 – 在Java中有一些方法可以强制将更改写入文件,这意味着它们(通常是?通常?通常?不确定)写入实际的底层文件(有点?非常?非常?)懒洋洋地说,这意味着它在一定时间内基本上只是一个共享的内存段。

从理论上讲,据我所知,内存映射文件实际上可以由共享内存段支持(我认为它们只是文件句柄),但我不知道在没有JNI的Java中这样做的方法。

我能想到几种类似的技术:

  1. 几年前,有一种名为JavaSpaces的技术,但是如果你问我的话,它似乎从来没有真正占据过,这是一种耻辱。
  2. 如今有分布式缓存技术,如Coherence和Tangosol 。

不幸的是,它们都没有合适的共享内存速度,但它们确实处理并发访问等问题。

最简单的方法是让两个进程实例化相同的内存映射文件。 实际上,它们将共享相同的堆外内存空间。 您可以获取此内存的物理地址,并使用sun.misc.Unsafe来写入/读取基元。 它通过putXXXVolatile / getXXXVolatile方法支持并发。 看看CoralQueue ,它可以在同一个JVM中轻松提供IPC以及线程间通信。

免责声明 :我是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上的写入吗? 对这个主题进行了非常有用的讨论。