PHP中的并发与多线程:高级水平

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:为什么PHP中的并发并非神话

\n

传统上,PHP被认为是一种同步语言,每个请求按顺序处理。然而,从视频处理到大数据解析等现代应用,都需要同时执行多个任务。没有并发,您可能会遇到“性能瓶颈”,即使强大的服务器也会在等待I/O操作完成时闲置。

\n

在本文中,我们将深入探讨PHP中的高级并发技术:从系统调用到内核级扩展。您将学习如何让PHP并行工作,同时不失去对资源的控制。

\n\n

1. 基础:PHP中的进程 vs 线程

\n

在深入代码之前,理解PHP上下文中进程与线程的区别非常重要。

\n
    \n
  • 进程——独立的实例,每个拥有自己的内存。通过pcntl_fork()创建。适用于重型任务,但需要进程间通信(IPC)。
  • \n
  • 线程——同一进程内的轻量级“子任务”,共享内存。通过pthreads扩展实现。非常适合处理共享数据,但需要同步。
  • \n
\n

在高级水平上,重要的是能够结合使用这两种方法。例如,使用fork隔离关键任务,而使用线程在同一个上下文中进行并行处理。

\n\n

1.1 通过pcntl_fork()实现并行进程

\n

系统调用pcntl_fork()创建一个子进程,复制父进程的内存。以下是并行处理多个URL的示例:

\n
<?php\n$urls = ['https://api.example.com/data1', 'https://api.example.com/data2', 'https://api.example.com/data3'];\n$pids = [];\n\nforeach ($urls as $url) {\n    $pid = pcntl_fork();\n    if ($pid == -1) {\n        die('无法创建进程');\n    } elseif ($pid) {\n        // 父进程:保存PID\n        $pids[] = $pid;\n    } else {\n        // 子进程:执行下载\n        $data = file_get_contents($url);\n        file_put_contents('/tmp/' . md5($url) . '.json', $data);\n        exit(0); // 终止子进程\n    }\n}\n\n// 等待所有进程完成\nforeach ($pids as $pid) {\n    pcntl_waitpid($pid, $status);\n}\necho "所有URL已并行处理!";\n?>
\n

重要提示:fork()后,子进程会继承所有打开的文件描述符和数据库连接。请在子进程中显式关闭它们,以避免冲突。

\n\n

2. 使用ReactPHP和Amp实现异步任务

\n

对于注重响应性的Web应用,请使用事件驱动循环库。ReactPHP和Amp允许执行非阻塞操作,而无需创建单独的进程。

\n\n

2.1 ReactPHP示例

\n

通过Composer安装库:composer require react/react。以下是一个异步HTTP客户端,同时发送三个请求:

\n
<?php\nrequire 'vendor/autoload.php';\n\nuse React\\EventLoop\\Factory;\nuse React\\HttpClient\\Client;\n\n$loop = Factory::create();\n$client = new Client($loop);\n\n$urls = ['http://example.com', 'http://example.org', 'http://example.net'];\n$promises = [];\n\nforeach ($urls as $url) {\n    $request = $client->request('GET', $url);\n    $request->on('response', function ($response) use ($url) {\n        echo "来自{$url}的响应:" . $response->getCode() . PHP_EOL;\n    });\n    $request->end();\n}\n\n$loop->run();\n?>
\n

ReactPHP创建一个单一的事件循环,无阻塞地处理所有请求。这对于API网关或微服务非常理想,因为响应速度至关重要。

\n\n

3. 使用pthreads管理线程(ZTS构建)

\n

pthreads扩展是在PHP中实现真正多线程的唯一方式。

博客

书籍推荐