前言

  最近在学习php多进程和多线程的编程。说实话,这两样在工作中几乎都没有用到,毕竟php并不以异步处理擅长,对于网络请求同步处理可以解决绝大多数问题。但是既然有这样的机制,也了解一下,对于以后接触别的语言也有好处。

php处理请求机制

   以nginx作为web服务器为例,nginx将对php发起的http请求交给FastCGI进程监听的IP地址及端口,由php-fpm(FastCGI Process Manager)作为动态解析服务器处理,最后再把处理结果交给nginx,nginx再返回给客户端。那么php-fpm如何处理呢?大家可能知道,php-fpm分 master进程和worker进程(如下图,来源网络)。master接受到请求,指派特定的worker进程来处理,worker进程处理请求,返回结果给nginx。想细致了解,可以参考:nginx和php之间是怎样通信的呢深入理解PHP之:Nginx 与 FPM 的工作机制

  从以上描述我们可以看出,一个单一的php-fpm worker就是同步阻塞,单进程单线程的处理机制。现在我们来讨论的是如何让一个php-fpm worker 实现多进程或多线程,以及这两种机制的比较。先来看看多进程和多线程的相关概念。

多进程和多线程的相关概念

  进程:进程是资源分配的最小单位;

  线程:线程是CPU调度的最小单位。

  选择多进程好还是选择多线程好?需要根据实际情况来判断,下面也是网络上对多线程和多进程的一番对比:

  

详细的请参考:多进程还是多线程的选择和区别 ,感觉这位牛人写的特别清楚。下面我们再来看看php环境下使用多进程和多线程要注意的。

php下多进程和多线程使用注意事项

  安装配置

  在php下使用多进程需要开启pcntl扩展。

  php下使用多线程需要开启pthread扩展,并且要求在php编译安装的时候就已经设置了线程安全(这个还是比较麻烦,需要重新编译安装php)。

  通信机制

  多进程和多线程下都可以使用全局变量。

  进程间的通信机制是管道(pipe)。

  在php下,由于线程安全的实现机制,线程间无法进行通信。

线程安全:线程安全是编程中的术语,指某个函数、函数库在多线程环境中被调用时,能够正确地处理多个线程之间的共享变量,使程序功能正确完成。

  PHP 实现的线程安全主要是使用 TSRM 机制对 全局变量和静态变量进行了隔离,将全局变量和静态变量 给每个线程都复制了一份,各线程使用的都是主线程的一个备份,从而避免了变量冲突,也就不会出现线程安全问题。同时 PHP 开启线程安全选项后,使用 TSRM 机制分配和使用变量时也会有额外的损耗。

CPU的使用

  从进程和线程的定义就可以知道,cpu一个核同一时间只能处理一个线程。所以单核cpu的服务器就不要考虑使用多线程或者多进程去做任务了,因为切换进程或者线程的开销让使用完全没有意义。但是多进程在守护进程的开发上还是有作用的。这个在单独介绍多进程的文章中详细说明。对于多核cpu可以根据实际情况选择多进程还是多线程。比如网络上很多例子提到的需要并发请求很多url,就可以用到多线程(无需线程间的通信)。 

--------------------------------------

2018.4.24补充一下,以上观点是错误的。对于单核CPU,如果任务是I/O密集型,则使用多线程或多进程仍然可以大幅缩短时间,和多核CPU效果是一样的,因为时间的瓶颈不在CPU而在I/O。但是CPU密集型,计算比较多的任务则单核CPU对多进程或多线程没有多大的优化效果。   

web环境下使用

  web环境下,不能使用多进程,这个官方文档有说明。

  web环境下,可以使用多线程。

  

参考资料:

nginx和php之间是怎样通信的呢

PHP多进程处理并行处理任务实例

深入理解PHP之:Nginx 与 FPM 的工作机制

多进程还是多线程的选择和区别

多线程编程 - PHP 实现

php多进程和多线程的比较的更多相关文章

  1. 从Nginx的Web请求处理机制中剖析多进程、多线程、异步IO

    Nginx服务器web请求处理机制 从设计架构来说,Nginx服务器是与众不同的.不同之处一方面体现在它的模块化设计,另一方面,也是最重要的一方面,体现在它对客户端请求的处理机制上. Web服务器和客 ...

  2. gdb调试多进程和多线程命令

     gdb调试多进程和多线程命令 来源:http://blog.csdn.net/pbymw8iwm/article/details/7876797 1. 默认设置下,在调试多进程程序时GDB只会调试主 ...

  3. Python3 多进程和多线程

    Unix/Linux操作系统提供了一个fork()系统调用,它非常特殊.普通的函数调用,调用一次,返回一次,但是fork()调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为 ...

  4. Python中的多进程与多线程(二)

    在上一章中,学习了Python多进程编程的一些基本方法:使用跨平台多进程模块multiprocessing提供的Process.Pool.Queue.Lock.Pipe等类,实现子进程创建.进程池(批 ...

  5. 多CPU,多核,多进程,多线程

    当面临这些问题的时候,有两个关键词无法绕开,那就是并行和并发. 首先,要先了解几个概念: 1.进程是程序的一次执行. 2.进程是资源分配的基本单位(调度单位). 3.一个进程可以包括多个线程. 4.在 ...

  6. python多进程和多线程

    多任务才有多进程和线程: 线程是最小的执行单元,而进程由至少一个线程组成.如何调度进程和线程,完全由操作系统决定,程序自己不能决定什么时候执行,执行多长时间. 多进程和多线程的程序涉及到同步.数据共享 ...

  7. Python多进程vs多线程

    多任务的两种方式:多进程和多线程. 如果用多进程实现Master-Worker,主进程就是Master,其他进程就是Worker. 如果用多线程实现Master-Worker,主线程就是Master, ...

  8. 学习python 多进程和多线程

    ''' 学习多进程和多线程 ''' import multiprocessing def deadLoop(): while True: pass if __name__ == '__main__': ...

  9. python 多进程和多线程的区别

    了解线程和进程 进程 程序:磁盘上的可执行二进制文件,并无运行状态. 进程:就是一个正在运行的任务实例(存活在内存里). 获取当前电脑的CPU核心数: pip install psutil >& ...

随机推荐

  1. Mysql中从一张表中的数据添加到另一张表

    A为原表 B为要加入的表$sql="insert into B select * from A where id=$id";

  2. Mysql 中如何创建数据库和数据表

    这里的数据库为:user  数据表为 aaa mysql –uroot –p                 进入mysql create database user;            创建数据 ...

  3. 『Python』PIL图像处理_形变操作

    使用PIL.Image进行简单的图像处理 # coding=utf-8 from PIL import Image import matplotlib.pyplot as plt def show_i ...

  4. 时间选择控件YearPicker(基于React,antd)

    不知道为什么蚂蚁金服团队没有在ant design的DatePicker中单独给出选择年份的组件,这给我们这种懒人造成了很大的痛苦,自己手造轮子是很麻烦的.毕竟只是一个伸手党,emmmmm..... ...

  5. c++中利用localtime_s函数格式化输出当地日期与时间

    Visual C++ 6.0开发环境中显示当地日期与时间主要通过localtime()函数来实现,该函数的原型在time.h头文件中,其语法格式如下: struct tm *localtime(xon ...

  6. Leetcode 1022. 可被 K 整除的最小整数

    1022. 可被 K 整除的最小整数  显示英文描述 我的提交返回竞赛   用户通过次数74 用户尝试次数262 通过次数75 提交次数1115 题目难度Medium 给定正整数 K,你需要找出可以被 ...

  7. Angular4.x 引入第三方 JS

    引入 Jquery 使用 angular-cli 新建 angular项目 1.安装 jquery npm install jquery --save 2..angular-cli.json 中引入 ...

  8. Java ip地址查询,根据ip接口获得ip所在省市区,邮编,运营商等

    早上一来,项目经理就说需要添加一个用户ip归属地查询功能,然后在网上搜罗半天,研究出一个比较简单的方法,通过接口返回地址json数据 有百度接口,新浪接口,这里用的是淘宝ip接口 通过淘宝IP地址库获 ...

  9. python django 访问static静态文件

    settings 文件配置: STATIC_URL = '/static/' STATICFILES_DIRS = ( os.path.join(BASE_DIR, 'static'),)PROJEC ...

  10. day12-python的类

    类的一般形式: 创建类我们一般用class关键字来创建一个类,class后面跟类名字,可以自定义,最后以冒号结尾,如下所示: class ClassName: '''类的说明''' 类的内容 类的内容 ...