Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么在php中使用多线程不是一个好主意?_Php_Multithreading_Pcntl - Fatal编程技术网

为什么在php中使用多线程不是一个好主意?

为什么在php中使用多线程不是一个好主意?,php,multithreading,pcntl,Php,Multithreading,Pcntl,我知道php没有线程。但在本教程中,他们展示了通过使用主机操作系统的能力来形成我们可以实现它。它还表示,它不会在生产代码中这样做。为什么这不是一个好主意 下面是一个示例代码 $processID = pcntl_fork(); if($processID) { echo "I'm in the parent process!"; } else { echo "I'm in the child process!"; } 这里是。没有“实现”这里,pcntl\u fork创建了

我知道php没有线程。但在本教程中,他们展示了通过使用主机操作系统的能力来形成我们可以实现它。它还表示,它不会在生产代码中这样做。为什么这不是一个好主意

下面是一个示例代码

$processID = pcntl_fork();
if($processID) {
     echo "I'm in the parent process!";
} else {
     echo "I'm in the child process!";
}
这里是。

没有“实现”这里,
pcntl\u fork
创建了一个新的过程。 如果您创建多个进程,您很可能会在某个时候遇到竞速情况—PHP不是为并行执行而设计的,您将遇到各种奇怪的错误和控制问题

在一个程序中使用多个进程也会变得非常复杂-您必须在互斥体上进行同步,并对相互依赖的算法进行排序


相反,您可以编写互相调用方法的类,这使您能够解决几乎任何问题-那些不使用
fork
就无法解决的问题很可能是因为设计不好;网站不需要执行长时间运行的任务,但它们可能会对它们进行排队,添加crontab条目就是一个例子。

PHP应该在服务于前端的Web服务器上运行。在一个典型的环境中,您有多个用户(web客户端)并行使用,以充分利用您的CPU核心。在这样的环境中,将工作从一个线程分割成多个线程通常是没有意义的。由于系统已经加载,线程需要额外的同步工作等。通常最好将“复杂”任务卸载到后端系统,然后报告。通过这种方式,完成复杂任务的后端系统可以独立扩展。此外,作业可以排队,以便用户获得即时报告(“我们正在工作”),然后获得关于正在完成的报告

使用
pcntl\u fork()
创建进程的副本,这可能是Web服务器进程的完整副本,它将尝试通过相同的网络连接(也正在复制)与客户端进行对话,从而导致完全混乱。它还将导致与先前存在的数据库连接等的混乱(至少两个进程都将尝试关闭它…因此第二个进程将收到数据库的混乱错误)

对于实际的线程,有一个不创建进程副本但共享同一进程的线程,该进程会破坏PHP的内存模型(假设一次一个线程中有一个请求,而与其他任何线程都不共享)。有些人使用这种方法,但将其卸载到其他系统通常会更好

人们经常进行IO操作(即数据库调用),这需要时间。在这种情况下,异步操作是可能的(即参见
mysqli_poll
mysqli_eau_query
),这基本上让您在CPU上做一些事情,同时等待IO并不时检查IO。

分叉是否会创建线程? 当我们分叉一个进程时,进程空间,也就是说,进程需要执行的库和代码所在的内存区域是重复的,不同但相关的进程随后会根据操作系统调度器的意愿在不同的内存区域继续执行

分叉进程和线程之间的区别是什么? 当我们创建线程时,我们告诉操作系统我们需要另一个执行单元,它可以在创建线程的进程所在的内存区域中运行

不同的操作系统如何实际实现线程和进程超出了本答案的范围,并不重要

为什么在前端分叉是个坏主意? 当您复制整个地址空间时,您也复制了Web服务器正在运行的内存区域,这显然会对您的操作系统造成严重破坏

为什么在前端穿线是个坏主意? 如果客户端脚本指示操作系统创建8个线程以直接响应web请求,并且100个客户端同时请求脚本,则您将指示操作系统同时执行800个线程

CPU和操作系统需要看起来非常不同才能成为一个好主意

穿线在哪里是个好主意? 多线程软件和功能强大的硬件无处不在;没有它,计算就不会是现在的样子

在Web基础设施的上下文中,mysql和其他数据库服务器是多线程的,事实上Apache可以在多线程基础设施中部署PHP,尽管我不推荐这样做

当我们观察像mysql这样的企业应用程序实际上是如何提供其极其复杂的服务时,我们可以看到它们的进程(因此线程)与web应用程序的基础结构完全隔离

这就是我们在支持线程的语言中使用线程的方式;我们设计的系统,其提供服务的方式是通过某种合理的IPC形式,我们将复杂的基础设施完全与简单的基础设施隔离开来:我们的web应用程序

PHP真的适合线程吗? PHP的内存模型是不共享的:这意味着每个解释器上下文,在PHP操作所需的结构和内存的意义上,都与任何其他上下文隔离

这必须是真实的,PHP才能按预期工作;一个不了解PHP工作方式的PHP线程实现将无法正常工作

pthreads竭尽全力确保内存模型不被破坏,每个线程实际上并不与任何其他线程直接共享内存

线真的适合我吗? 首先,认真思考以下问题:

  • 真的需要线程吗
  • 你还能找到什么其他方法来实现你的目标
多线程软件本质上是复杂的;复杂的事情不是一种例外