线程同步与进程间通信
2026/8/24大约 3 分钟
线程同步与进程间通信
多线程编程中需要解决线程同步与进程间通信(IPC)两大问题。本章梳理临界区、互斥量、信号量等同步机制,以及 Linux 常用的 IPC 方式。
一、线程间同步机制
| 机制 | 原理 | 特点 |
|---|---|---|
| 临界区 | 每个线程中访问临界资源的代码;一个线程拿到临界区所有权后可以多次重入,只有前一个线程放弃后一个线程才能进入 | 只能用于同一进程内的线程互斥 |
| 互斥量 | 简化版的信号量,有线程所有权概念,只能进行线程间资源互斥访问 | 是内核对象,可进行进程间通信;能解决"遗弃"问题 |
| 信号量 | 用法与互斥量相似,但同一时刻可允许多个线程访问同一个资源(PV 操作) | 也是内核对象,可进行进程间通信 |
要点:
- 互斥量是内核对象,因此可以进行进程间通信;临界区仅限进程内。
- 信号量同一时刻允许 N 个线程访问同一资源(N 由初始值决定),互斥量同一时刻只允许一个。
二、进程间通信(IPC)
| 方式 | 特点 | 说明 |
|---|---|---|
| 管道(pipe) | 半双工 | 只能在具有父子关系的进程间使用,基于 FIFO 的共享内存实现 |
| 命名管道 | 半双工 | 以 Linux 中文件的形式存在,不要求进程有父子关系,甚至可通过网络使用 |
| 信号量 | up / down 操作 | 基于共享内存实现,用于同步与互斥 |
| 消息队列 | 队列数据结构 | 基于共享内存实现,传递有格式消息 |
| 信号(signal) | 较为复杂 | 用于通知进程某事件已经发生,例如 kill 信号 |
| 共享内存 | 最快 | 将同一个物理内存附属到两个进程的虚拟内存中 |
| 套接字(Socket) | 可跨网络 | 用于不同机器之间的进程间通信 |
三、同步与互斥
同步: 多个线程/进程按照约定的先后次序协作执行(例如生产者-消费者:生产者在缓冲区满时等待,消费者在缓冲区空时等待)。
互斥: 多个线程/进程对共享资源的访问是排他的,同一时刻只允许一个访问者使用资源。
互斥是一种特殊的同步(制约关系更小的同步)。多线程编程中核心问题就是防止两个或两个以上的线程同时访问同一个数据,以免破坏数据的完整性。
四、Java 中的对应实现
| Linux 概念 | Java 对应 |
|---|---|
| 临界区 | synchronized 代码块 / ReentrantLock |
| 互斥量 | synchronized / ReentrantLock(可重入) |
| 信号量 | Semaphore(允许多个许可) |
| 消息队列 | BlockingQueue 等并发队列 |
| 共享内存 | 线程共享堆内存 / volatile |
更多并发细节见《Java 并发编程》相关文章。