pcntl_fork如何在PHP中运行?

时间:2012-06-03 14:49:54

标签: php fork pcntl

我对PHP中的pcntl_fork感到困惑。

我认为它确实是多线程的,但它是如何工作的以及如何在脚本中使用它?

1 个答案:

答案 0 :(得分:40)

PCNTL无法创建线程。它只是“分叉”当前的PHP进程。这是什么意思?当您致电pcntl_fork()时,当前流程将分为两个流程。父进程的整个命名空间被复制到子进程中,并且两个进程继续并行执行,只有一个区别:pcntl_fork()返回父级的子级PID和子级的0

一些提示:

  • 默认情况下禁用。如果您设法启用它,则仅针对CLI执行此操作。永远不要在网络服务器上使用它!它将以非确定性的方式表现。它也可以降低整机性能。请保持禁用并继续阅读。
  • 流程之间的沟通是可能的,但可怕的(通过 共享内存中的序列化对象)。
  • 文件描述符(和数据库 连接)是共享的,这经常导致问题。 您必须在分叉后重新连接数据库,否则当第一个分叉进程关闭连接时,您将从所有分叉进程中收到MySQL server has gone away等错误。
  • 父进程必须等待孩子完成,否则将离开僵尸 消耗系统资源的过程。

以下为示例from documentation

<?php

$pid = pcntl_fork();
if ($pid == -1) {
     die('could not fork');
} else if ($pid) {
     // we are the parent
     pcntl_wait($status); //Protect against Zombie children
} else {
     // we are the child
}

但请记住,PHP只是脚本语言。它不是为并行计算而设计的。根据您的需要,您可以同时运行CRON,消息队列或低级语言程序,从而做得更好。

Forked PHP程序很难阅读,理解和调试。维持该计划将是一场噩梦。

不要犯错误并避免分叉。你不需要它。你真正需要的是异步任务运行器。好消息,有RabbitMQnice tutorial ;-)你也可以尝试一下名为Bunny的有希望的RabbitMQ库

PS:使用消息队列而不是分叉为您提供了另一个优势。您可以使用多个服务器处理队列,并在流量增长时水平扩展。

编辑2019-03-07

我使用异步并发框架amphp玩了很多,我必须在这里提一下。如果您确实需要在单个请求中运行异步非阻塞任务,我认为amphp是今天最好的解决方案。它使用php生成器($value = yield $promise)的概念来执行人类可读的代码而没有像reactphp一样的承诺地狱。

https://amphp.org/