进程间通信
问题
进程间通信(IPC)有哪些方式?各自的优缺点和适用场景?
答案
IPC 方式对比
| 方式 | 原理 | 速度 | 适用场景 |
|---|---|---|---|
| 管道(Pipe) | 半双工,父子进程间 | 中等 | 简单的命令行管道 |
| 命名管道(FIFO) | 文件系统中的特殊文件 | 中等 | 无亲缘关系进程 |
| 消息队列 | 内核维护的消息链表 | 中等 | 结构化消息传递 |
| 共享内存 | 多个进程映射同一块内存 | 最快 | 大量数据交换 |
| 信号量 | 计数器,控制并发 | 快 | 进程同步 |
| 信号(Signal) | 异步通知 | 快 | 进程控制(kill) |
| Socket | 网络通信 | 较慢 | 跨机器通信 |
管道
# Linux 管道示例
ls -la | grep ".md" | wc -l
# ls 的输出 → grep 的输入 → wc 的输入
- 半双工:数据只能单向流动
- 只用于有亲缘关系的进程(父子进程)
共享内存
最快的 IPC 方式,因为数据不需要在内核和用户空间之间拷贝。但需要配合信号量做同步控制。
进程 A 共享内存区域 进程 B
[写入数据] ----→ [内存映射同一物理页] ←---- [读取数据]
Java 中的 IPC
| 方式 | 说明 |
|---|---|
| Socket | 最常用,跨网络通信 |
ProcessBuilder | 启动子进程,通过标准输入/输出通信 |
| MappedByteBuffer | 内存映射文件(共享内存) |
| RMI | Java 远程方法调用 |
| MQ | 消息队列(Kafka、RabbitMQ) |
常见面试问题
Q1: 为什么共享内存最快?
答案:
其他 IPC 方式(管道、消息队列)需要将数据从发送进程的用户空间拷贝到内核空间,再从内核空间拷贝到接收进程的用户空间——两次拷贝。
共享内存直接将同一块物理内存映射到两个进程的地址空间,进程直接读写不经过内核,零次内核拷贝。
Q2: 线程间通信和进程间通信有什么区别?
答案:
线程共享进程的内存空间,所以线程间通信简单得多:
- 共享变量 + synchronized/volatile
- wait/notify
- BlockingQueue
- CompletableFuture
进程有独立的内存空间,必须通过操作系统提供的 IPC 机制通信。