PHP中的并发与多线程:现代方法
PHP传统上与同步代码执行相关联。然而,现代Web应用程序需要同时处理多个任务:从文件上传到大数据解析。在本文中,我们将探讨如何使用内置和第三方工具在PHP中实现并发与多线程。
什么是并发与多线程?
并发是指程序通过任务切换"同时"执行多个任务的能力。多线程是并发的一种特殊情况,任务在操作系统的独立线程中执行。
在PHP 7.4之前,没有对线程的原生支持。但随着pthreads和parallel扩展的出现,以及进程处理能力的改进,情况发生了变化。
1. 使用parallel扩展实现多线程
parallel扩展是PHP 7.4+中处理线程的现代方式。它使用共享内存,允许在线程之间高效地交换数据。
安装:
pecl install parallel创建线程示例:
<?phpuse parallel\\Runtime;
$runtime = new Runtime();$future = $runtime->run(function() { // 繁重的计算 $result = 0; for ($i = 0; $i < 1000000; $i++) { $result += sqrt($i); } return $result;});
echo "主线程继续工作...";$result = $future->value(); // 获取结果echo "结果: $result";?>parallel的优势:
- 原生线程支持,无需额外依赖
- 线程间共享内存
- 支持传递闭包和对象
缺点:
- 需要PHP 7.4+和ZTS(Zend线程安全)
- 不支持Windows
- 调试困难
2. 通过进程实现异步:pcntl_fork
如果不需要共享内存,可以使用pcntl_fork()处理进程。这是经典的Unix方法。
<?php$pid = pcntl_fork();
if ($pid == -1) { die("进程创建失败");} elseif ($pid) { // 父进程 echo "父进程:等待子进程..."; pcntl_wait($status); echo "父进程:子进程已完成";} else { // 子进程 echo "子进程:执行任务..."; sleep(3); exit(0);}?>进程处理的特性:
- 每个进程拥有独立的内存
- 使用套接字、共享内存(shmop)或文件进行数据交换
- 需要通过
pcntl_wait()处理僵尸进程
3. 通过异步函数和ReactPHP实现并发
对于I/O任务(网络请求、文件读取),使用ReactPHP或Amp等异步库更高效。它们不创建线程,但通过事件循环实现并发执行。
ReactPHP示例:
<?phprequire 'vendor/autoload.php';
use React\\EventLoop\\Factory;use React\\Http\\Browser;
$loop = Factory::create();$client = new Browser($loop);
$promises = [];$urls = [ 'https://api.example.com/data1', 'https://api.example.com/data2', 'https://api.example.com/data3'];
foreach ($urls as $url) { $promises[] = $client->get($url);}
// 并行等待所有请求$results = [];foreach ($promises as $promise) { $results[] = $promise->wait();}
$loop->run();print_r($results);?>