以下是关于进程、线程和协程的详细对比,并附上对应的 PHP 代码示例,帮助理解它们的区别和联系。
一. 进程(Process)
特点
- 独立内存空间,进程间通信(IPC)需要特殊机制(如管道、共享内存)。
- 创建和切换开销大,由操作系统调度。
- 稳定性高,一个进程崩溃不会影响其他进程。
PHP 代码示例
PHP 本身是单线程的,但可以通过 pcntl_fork()
创建子进程(仅支持 Unix/Linux 系统):
<?php
$pid = pcntl_fork();
if ($pid == -1) {
die("fork failed");
} elseif ($pid) {
// 父进程
echo "Parent process (PID: " . getmypid() . ")\n";
pcntl_wait($status); // 等待子进程结束
} else {
// 子进程
echo "Child process (PID: " . getmypid() . ")\n";
sleep(2);
exit(0); // 子进程退出
}
运行结果:
Parent process (PID: 1234)
Child process (PID: 1235)
二. 线程(Thread)
特点
- 共享进程的内存,线程间通信更高效,但需要同步机制(如锁)。
- 创建和切换比进程轻量,但仍由操作系统调度。
- PHP 原生不支持多线程,但可以通过
pthreads
扩展(仅 CLI 模式)。
PHP 代码示例
<?php
class MyThread extends Thread {
public function run() {
echo "Thread running (TID: " . $this->getThreadId() . ")\n";
sleep(1);
}
}
$thread1 = new MyThread();
$thread2 = new MyThread();
$thread1->start(); // 启动线程1
$thread2->start(); // 启动线程2
$thread1->join(); // 等待线程1结束
$thread2->join(); // 等待线程2结束
运行结果:
Thread running (TID: 1)
Thread running (TID: 2)
三. 协程(Coroutine)
特点
- 用户态轻量级线程,由程序控制切换,不依赖操作系统调度。
- 适用于高并发 I/O 操作(如网络请求、数据库查询)。
- PHP 通过
Swoole
或Fiber
(PHP 8.1+)支持协程。
PHP 代码示例(Swoole 协程)
<?php
use Swoole\Coroutine;
Coroutine::create(function () {
echo "Coroutine 1 start\n";
Coroutine::sleep(1); // 模拟 I/O 操作
echo "Coroutine 1 end\n";
});
Coroutine::create(function () {
echo "Coroutine 2 start\n";
Coroutine::sleep(0.5);
echo "Coroutine 2 end\n";
});
echo "Main script continues\n";
运行结果:
Coroutine 1 start
Coroutine 2 start
Main script continues
Coroutine 2 end
Coroutine 1 end
(协程是非阻塞的,Main script continues
会先输出,协程在后台执行。)
四. 三者的对比总结
1. 核心区别
维度 | 进程 | 线程 | 协程 |
---|---|---|---|
定义 | 操作系统资源分配的基本单位 | CPU调度的基本单位(属于进程) | 用户态轻量级线程(程序控制) |
独立性 | 独立内存空间,互不干扰 | 共享进程内存,需同步机制 | 共享线程资源,无同步问题 |
切换开销 | 高(涉及内核态切换) | 中(仍需内核调度) | 极低(用户态自主切换) |
并发性 | 多进程并行(多核) | 多线程并行(多核) | 单线程内伪并发(协作式) |
典型场景 | 浏览器多标签页、独立应用 | 视频解码、文件读写 | 高并发I/O(如爬虫、Web服务器) |
2. 联系与协作
-
进程是线程的容器
- 一个进程至少包含1个线程(主线程),线程共享进程的内存(如堆、全局变量),但各自有独立的栈和寄存器。
- 例子:Chrome浏览器用多进程隔离标签页(安全),每个标签页内又用多线程处理渲染、网络请求等。
-
协程是线程的优化
- 协程运行在线程上,通过协作式调度(主动让出CPU)避免线程切换的开销。
- 例子:Python的
asyncio
用单线程+协程处理数万并发网络请求,比多线程更高效。
-
三者的演进逻辑
- 进程 → 解决程序间隔离问题,但太重;
- 线程 → 轻量化并发,但同步复杂;
- 协程 → 极致轻量,适合I/O密集型任务。
3. 经典比喻
- 进程 = 独立的工厂(有专属车间和仓库)
- 线程 = 工厂的工人(共享车间,但可能抢工具)
- 协程 = 工人手上的流水线(自主决定何时停工/复工)
4. 如何选择?
- 需要隔离性 → 用进程(如安全敏感的金融系统)。
- 需要并行计算 → 用多线程(如视频转码)。
- 需要高并发I/O → 用协程(如Web服务器、爬虫)。