在 Ubuntu 上给 PHP 加点“多线程”的能力,其实路数还挺多的。不过,PHP 的多线程和我们通常理解的那种多线程(比如 Ja va 里的)有些差别,得根据实际场景来选。下面直接说几个关键点。

1. 用 pthreads 扩展,硬核但有限制
pthreads 是 PHP 官方扩展,能让你真正创建和管理线程。但有个硬性条件:它只能在 CLI(命令行)模式下跑,而且编译 PHP 时得把 pthreads 支持打进去。换句话说,这玩意儿跟 Web 服务器下的 PHP 进程基本没关系。
怎么装?
- 先装基础依赖:
sudo apt-get update
sudo apt-get install php-dev php-pear
- 安装
pthreads本身:
sudo pecl install pthreads
- 编辑
php.ini(通常路径类似于/etc/php/7.x/cli/php.ini),加上一行:
extension=pthreads.so
- 重启 Web 服务器——如果用的是 Apache:
sudo systemctl restart apache2
如果是 PHP-FPM,则换成:
sudo systemctl restart php7.x-fpm
跑个例子看看
start();
$thread->join();
?>
这段代码会创建一个线程,执行 run() 方法里的逻辑,然后主线程等待它结束。简单直接,但要记住:只在 CLI 下有效。
2. 用 pcntl 扩展,模拟多进程
pcntl 提供的是进程控制能力(fork、wait 等),不是线程。但它能通过创建子进程来模拟并行的效果。好处是部署简单,缺点是多进程的通信和同步比多线程重一些。
安装流程和 pthreads 类似
- 先装依赖:
sudo apt-get update
sudo apt-get install php-dev php-pear
- 安装
pcntl:
sudo pecl install pcntl
- 在
php.ini里加上:
extension=pcntl.so
- 重启 Apache 或 PHP-FPM。
来一段经典的 fork 代码
这里 pcntl_fork() 返回子进程的 PID(给父进程)或 0(给子进程)。父进程调用 pcntl_wait() 阻塞等待子进程结束。这个方法适合处理需要独立运行的并行任务,比如批量处理文件、多个网络请求等。
3. 用事件驱动库 ReactPHP 或 Amp 实现并发
如果不想和进程、线程较劲,只想在同一个进程里高效处理多个 I/O 操作(比如同时发 HTTP 请求、读写文件),那用事件循环的自定义方式更合适。ReactPHP 和 Amp 都是 PHP 生态里成熟的异步 / 非阻塞库。
以 ReactPHP 为例
- 先装依赖:
sudo apt-get update
sudo apt-get install php-dev php-pear
- 通过 Composer 安装
ReactPHP:
composer require react/react
演示一段定时任务
addPeriodicTimer(1, function () {
echo "Tick\n";
});
$loop->addPeriodicTimer(2, function () {
echo "Tock\n";
});
$loop->run();
?>
这段代码会在事件循环中注册两个定时器:一个每秒触发打印 “Tick”,另一个每两秒触发打印 “Tock”。事件循环会一直运行,直到没有事件需要处理。这个模型特别适合做 WebSocket 服务器、袋里服务器或者需要处理大量并发连接的后台服务。
总结一下
pthreads:适合 CLI 下需要真正多线程的场景,但部署和运维要求较高(必须编译时启用支持,且只能在命令行下跑)。pcntl:用多进程模拟多线程,部署简单,但进程间通信成本较高,适合任务粒度大且互相独立的场景。ReactPHP/Amp:事件驱动,同一个进程内实现高效并发,适合 I/O 密集型的并发任务,代码写起来更像回调或协程的写法。
选哪个,得看具体的业务场景——是需要在后台并行跑计算任务?还是同时处理多个网络请求?又或者是做一个高并发的 Web 服务?没有银弹,但了解这几种方式的适用范围后,方向就很清楚了。
