PHP 阻塞非阻塞


进程阻塞

正在运行的进程 由于提出 系统服务请求 如I/O操作 但因为某种原因 未得到 操作系统的 立即响应 或 需要从其他合作进程获得的数据 尚未到达等 该进程只能调用阻塞原语把自己阻塞 等待相应的事件出现后才被唤醒

阻塞状态

正在进行的 进程 由于发生某事件 而暂时无法继续执行时 便放弃处理机 而处于暂停状态 即进程的执行受到阻塞 这种暂停状态叫 阻塞进程阻塞 有时也成为 等待状态 或 封锁状态 通常这种处于 阻塞状态 的进程也排成一个队列 有的系统则根据阻塞原因的不同而 处于阻塞状态 进程排成多个队列

用户访问服务端 请求用户的个人的订单信息 由于数据库数据量大 数据库繁忙 sql语句查询了3秒才返回 这个查询数据库的过程 就是可称为是 阻塞的 进程调用外部逻辑

这个并不是进程本身执行所消耗的时间 而是因为查询数据库 等待数据库响应消耗的时间 阻塞的危害性和时间有关 阻塞0.1秒 对于用户是没有任何问题的 但是阻塞10秒将会使用户体验下降很多 所以 需要重视阻塞

用户访问服务端 由于某个地方调用了死循环或多重循环浪费了许多时间 无法继续往下执行 这个状态也可称为阻塞  
非进程阻塞 在进程阻塞层面中 并不算是被阻塞了 因为它依旧在执行进程中的代码 没有等待清空

阻塞函数

调用数据库等外部逻辑 造成阻塞的函数 就叫做 阻塞函数

php 阻塞

阻塞 和 同步 概念一起存在的 例如查询数据库 获取文件数据 请求其他网站 等等 只要需要消耗非进程本身执行时间 并需要进程等待(同步)的 都可以说是阻塞

几乎所有的阻塞 都是与I/O有关
阻塞 是同步代码 调用阻塞函数 才会阻塞 但同步代码不一定会阻塞 (不调用阻塞函数的同步代码)

<?php$num = 30;$result = M('test')->select();//伪代码 sql阻塞sleep(3);//伪代码 当成执行了3秒才返回echo json_encode($result);//返回数据

非阻塞

在进程在运行中 不存在阻塞情况 一直能往下执行

非阻塞 调用I/O操作时 进程无需等待I/O操作 直接往下执行的情况非阻塞通常是和 异步 概念一起存在 只要是异步获取I/O 就一定是非阻塞
异步调用I/O一定是非阻塞的 但非阻塞不一定需要异步调用才可实现(非阻塞模型)

当查询数据库时 马上返回状态(查询到了就返回数据 数据还没到就返回-1) 程序可以立即往下执行逻辑

这种马上返回结果 无需等待(并不一定有数据)的函数 就叫做非阻塞函数 也可称为是 异步调用

非阻塞模型

可以通过 非阻塞模型  实现 非阻塞(主要针对于server服务端实现)

php中的非阻塞

php 有非阻塞  例如 socket_set_nonblock() 函数 将socket改为非阻塞状态
通过flock($file LOCK_EX|LOCK_NB) 可将文件操作设置为非阻塞状态

非阻塞注意事项

由于非阻塞的返回结果是不确定的 需要关心返回结果的情况时 需要确保返回结果是正确的(例如while(1){}定时查询 当数据正确返回退出循环) 或者直接使用阻塞函数

阻塞和非阻塞的举例

阻塞
小明去电脑店买Mac 问店员现在有没有MacBook Pro版本 有多少台 店员告诉小明 "我得去查一查 你得等等" 小明站在店门口等了2天 店员回来了 告诉小明 现在有10台 然后小明买了一台.

在这个过程中 店员查询是否有MacBook Pro的动作 就属于I/O操作 叫小明等等这个操作 就是阻塞情况 小明等了2天 就说明查询MacBook Pro时间为2天 阻塞了2天 店员回来告诉小明有10台 就是阻塞函数出现了结果 并返回了数据 小明买了一台 就是继续往下执行了代码

非阻塞 小明去电脑店买Mac 问店员现在有没有MacBook Pro版本 店员告诉小明 "我得去查一查 你先回去呗" 小明回家 每隔10分钟打电话给店员 但是店员每次都告诉他还没查到 小明每次打完电话就去敲PHP代码 2天后 小明打完一把LOL 又打电话给店员问 店员告诉小明 现在有10台了 然后小明买了一台

在这个过程中 店员查询是否有MacBook Pro的动作 就属于I/O操作 叫小明回家这个操作 就是非阻塞情况 小明不断打电话 这个就是定时轮询查询 店员不断的回复 这个情况就是非阻塞函数没有返回数据 小明去敲PHP 说明非阻塞情况还能执行其他代码 2天后 店员回来告诉小明有10台 就是非阻塞函数通过轮询出现了结果 并返回了数据 小明买了一台 就是退出了循环继续往下执行了代码