Java 中共享内存的任何概念

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1491519/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 13:23:24  来源:igfitidea点击:

Any concept of shared memory in Java

javamemoryshared

提问by

AFAIK, memory in Java is based on heap from which the memory is allotted to objects dynamically and there is no concept of shared memory.

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

If there is no concept of shared memory, then the communication between Java programs should be time consuming. In C where inter-process communication is quicker via shared memory compared to other modes of communication.

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

Correct me if I'm wrong. Also what is the quickest way for 2 Java progs to talk to each other.

如果我错了纠正我。还有什么是 2 Java progs 相互交谈的最快方式。

采纳答案by Aaron Digulla

Since there is no official API to create a shared memory segment, you need to resort to a helper library/DDL and JNI to use shared memory to have two Java processes talk to each other.

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

In practice, this is rarely an issue since Java supports threads, so you can have two "programs" run in the same Java VM. Those will share the same heap, so communication will be instantaneous. Plus you can't get errors because of problems with the shared memory segment.

实际上,这很少成为问题,因为 Java 支持线程,因此您可以在同一个 Java VM 中运行两个“程序”。它们将共享同一个堆,因此通信将是即时的。另外,您不会因为共享内存段的问题而出错。

回答by Will

Shared memory is sometimes quick. Sometimes its not - it hurts CPU caches and synchronization is often a pain (and should it rely upon mutexes and such, can be a major performance penalty).

共享内存有时很快。有时它不是 - 它会损害 CPU 缓存,同步通常是一种痛苦(如果它依赖互斥锁等,可能是一个主要的性能损失)。

Barrelfishis an operating system that demonstrates that IPC using message passing is actually faster than shared memory as the number of cores increases (on conventional X86 architectures as well as the more exotic NUMA NUCA stuff you'd guess it was targeting).

Barrelfish是一个操作系统,它表明随着内核数量的增加,使用消息传递的 IPC 实际上比共享内存更快(在传统的 X86 架构上,以及你猜想它的目标是更奇特的 NUMA NUCA 东西)。

So your assumption that shared memory is fast needs testing for your particular scenario and on your target hardware. Its not a generic sound assumption these days!

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

回答by Nick Holt

There's a couple of comparable technologies I can think of:

我能想到一些可比的技术:

  1. A few years back there was a technology called JavaSpacesbut that never really seemed to take hold, a shame if you ask me.
  2. Nowadays there are the distributed cache technologies, things like Coherenceand Tangosol.
  1. 几年前,有一种叫做JavaSpaces的技术,但它似乎从未真正站稳脚跟,如果你问我,那真是太遗憾了。
  2. 现在有分布式缓存技术,比如CoherenceTangosol

Unfortunately neither will have the out right speed of shared memory, but they do deal with the issues of concurrent access, etc.

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

回答by Cowan

One thing to look at is using memory-mapped files, using Java NIO's FileChannelclass or similar (see the map() method). We've used this very successfully to communicate (in our case one-way) between a Java process and a C native one on the same machine.

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

I'll admit I'm no filesystem expert (luckily we do have one on staff!) but the performance for us is absolutely blazingly fast -- effectively you're treating a section of the page cache as a file and reading + writing to it directly without the overhead of system calls. I'm not sure about the guarantees and coherency -- there are methods in Java to force changes to be written to the file, which implies that they are (sometimes? typically? usually? normally? not sure) written to the actual underlying file (somewhat? very? extremely?) lazily, meaning that some proportion of the time it's basically just a shared memory segment.

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

In theory, as I understand it, memory-mapped files CAN actually be backed by a shared memory segment (they're just file handles, I think) but I'm not aware of a way to do so in Java without JNI.

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

回答by Ashwin Jayaprakash

There are at least 2 ways to do it - RAM Driveor Apache APR.

至少有两种方法可以做到——RAM 驱动器Apache APR

Details hereand herewith some performance measurements.

此处此处的详细信息以及一些性能测量。

回答by Ashwin Jayaprakash

Peter Lawrey's Java Chronicleproject is worth looking at.

Peter Lawrey 的Java Chronicle项目值得一看。

These are some teststhat I had done a while ago comparing various off-heap and on-heap options.

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

回答by Peter Schaeffer

The information provided by Cowan is correct. However, even shared memory won't always appear to be identical in multiple threads (and/or processes) at the same time. The key underlying reason is the Java memory model (which is built on the hardware memory model). See Can multiple threads see writes on a direct mapped ByteBuffer in Java?for a quite useful discussion of the subject.

Cowan 提供的信息是正确的。但是,即使共享内存在多​​个线程(和/或进程)中同时出现也不会总是相同。关键的根本原因是 Java 内存模型(它建立在硬件内存模型之上)。请参阅多线程可以看到在 Java 中直接映射的 ByteBuffer 上的写入吗?对这个主题进行了非常有用的讨论。

回答by pcdv

Similar to Peter Lawrey's Java Chronicle, you can try Jocket.

与 Peter Lawrey 的 Java Chronicle 类似,您可以尝试Jocket

It also uses a MappedByteBuffer but does not persist any data and is meant to be used as a drop-in replacement to Socket / ServerSocket.

它还使用 MappedByteBuffer 但不保留任何数据,旨在用作 Socket / ServerSocket 的直接替代品。

Roundtrip latency for a 1kB ping-pong is around a half-microsecond.

1kB 乒乓的往返延迟约为半微秒。

回答by rdalmeida

The easiest way to do that is to have two processes instantiate the same memory-mapped file. In practice they will be sharing the same off-heap memory space. You can grab the physical address of this memory and use sun.misc.Unsafeto write/read primitives. It supports concurrency through the putXXXVolatile/getXXXVolatile methods. Take a look on CoralQueuewhich offers IPC easily as well as inter-thread communication inside the same JVM.

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

Disclaimer: I am one of the developers of CoralQueue.

免责声明:我是 CoralQueue 的开发人员之一。

回答by MikaelJ

MappedBus (http://github.com/caplogic/mappedbus) is a library I've added on github which enable IPC between multiple (more than two) Java processes/JVMs by message passing.

MappedBus ( http://github.com/caplogic/mappedbus) 是我在 github 上添加的一个库,它通过消息传递在多个(超过两个)Java 进程/JVM 之间启用 IPC。

The transport can be either a memory mapped file or shared memory. To use it with shared memory simply follow the examples on the github page but point the readers/writers to a file under "/dev/shm/".

传输可以是内存映射文件或共享内存。要将它与共享内存一起使用,只需遵循 github 页面上的示例,但将读取器/写入器指向“/dev/shm/”下的文件。

It's open source and the implementation is fully explained on the github page.

它是开源的,其实现在 github 页面上有完整的解释。