奔逸绝尘鸿 发表于 2024-8-6 15:45:15

一直让 PHP 程序员懵逼的同步阻塞异步非阻塞,终于搞明白了

大家好,我是码农先森。
经常听到身边写 Java、Go 的朋友提到程序异步、非阻塞、线程、协程,让系统性能提高到百万、千万并发,使我甚是惊讶属实羡慕。对于常年写 PHP 的我来说,最初听到这几个词时,脑袋一直处于蒙圈状态,回过头来看着自己手上同步阻塞的 PHP 代码,心想着「异步、非阻塞、线程、协程」到底是个什么东东,这么厉害嘛。其实 PHP 中也有线程、协程,但在日常的编程中几乎不会使用,原因是 PHP-FPM 多进程模式下并不支持线程、协程,使用 PHP 编程的程序员绝大多数都离不开 PHP-FPM 。这也就导致了 PHP 程序员对那些概念没有接触,那就更别提理解了,因此为了广大的 PHP 程序员同胞们能够和 Java、Go 的程序员对上话,特地对「同步、阻塞、异步、非阻塞」这几个概念进行了深度的分析,争取把 PHP 程序员的腰杆挺直溜。
按照惯例先上八股文这道菜:

[*]同步阻塞:当一个操作被调用时,调用者将被阻塞,直到这个操作完成并返回结果。在此期间,调用者无法进行其他任务。
[*]异步阻塞:当一个操作被调用时,调用者不会被阻塞,而是可以继续执行其他任务。然而,它仍然需要等待被调用的操作完成,并在操作完成后处理其结果。这个等待过程可能是阻塞的。
[*]同步非阻塞:调用者发起一个操作后,不会被阻塞并可以继续执行其他任务。虽然调用者可以立即获得控制权,但它仍然需要等待操作完成才能处理结果。在等待的过程中,调用者可以主动轮询或者不断尝试获取操作结果,以避免长时间的阻塞。
[*]异步非阻塞:调用者发起一个操作后,不会被阻塞并可以继续执行其他任务。同时,调用者也不需要等待操作完成来处理结果。相反,调用者可以注册一个回调函数或者使用类似事件驱动的机制,当操作完成后被自动触发回调函数来处理结果。
基础知识扎实的朋友看这个八股文就足以解惑了,不过看得懂八股文的毕竟是少数英俊帅气人,你说气不气人集颜值与才华于一体,别看说的就是各位看官「哈哈」。言归正传,那看不懂八股文的怎么搞?别急,且听我结合生活中的例子娓娓道来。

你每天上班匆匆路过的早餐店,今天额外的多人,你凑近一看原来是来了位身材高挑楚楚动人的美女服务员,结果你按耐不住心中的激动,今天高低得买两个馒头外加一杯豆浆,由于买的人太多,蒸好的馒头早已卖完,这时你只能等正在蒸的,期间你什么也干不了只能眼勾勾的干等着,那么这时的你是同步阻塞的。
由于来买早餐的人越来越多,离上班的时间也越来越近,你开始了骚动,每隔几分钟就问美女服务员馒头蒸好了没?此时的你不再干等,而是开始刷刷抖音看看工作群,因为你已经付钱了所以还是得等馒头,由于美女服务员太忙了没空主动告诉你,需要你自己不断地问,那么这时的你是同步非阻塞的。
过了高峰期人变少了,视野更广阔了,你看美女服务员更清楚了,结果你又开始眼勾勾的干等着,抖音也不刷了工作群的消息也不顾了。由于美女服务员不忙了,开始主动叫那位身穿格子衫背双肩包帅哥,馒头蒸好了,这时的你甩了甩头上的刘海,接过了美女服务员手中的馒头会心一笑,顺便还加了对方的微信,那么此时的你是异步阻塞的。
隔天你为了再睹芳容,又来到了这家早餐店,一向抠门的你甩手就点了两个肉包。这时美女服务员迎面笑脸告知你肉包还需耐心等待哦,蒸好了会微信通知你。在炎炎的夏日里你路上走的太匆忙,此时的你口渴难耐,就去隔壁小卖部买了瓶82年的可乐,还坐着吹了会空调。随着微信的一声叮咚,你起身去早餐店,接过了美女服务员手中的肉包,那么此时的你是异步非阻塞的。
有了美女服务员的投喂,你工作的干劲都十足了,同时应该也把「同步、阻塞、异步、非阻塞」这几个概念搞懂了吧。其实这里的同步异步和阻塞非阻塞,容易搞混淆就像你看美女服务员容易丢魂一样,在这个例子中同步异步需要关注的是「美女服务员是否会主动的通知你」,主动通知你那么对你来说就是异步的,需要你去询问那么对你来说就是同步的。阻塞非阻塞需要关注的点是「你是否是眼勾勾的干等着」,如果你只能干等那就是阻塞的,如果你还能干点其他的事情比如刷抖音、买82年的可乐,那么就是非阻塞的。
美女也看了道理也懂了,有的朋友们又要产生新的疑问了,那在程序中怎么体现、怎么用「同步、阻塞、异步、非阻塞」呢?那我们就开始上代码,毕竟看美女服务员的目的也是为了能够深入交往嘛,也就等同于实践上手了,你细品是不是这个理。
开整!
我们先来看同步阻塞的例子,使用 socket_create、socket_bind、socket_listen 函数创建绑定并监听了 8080 端口,然后一直阻塞在 socket_accept 函数上,直到有客户端连接的到来。传统的 PHP-FPM 就是同步阻塞的模式,不过 PHP-FPM 多进程模型,在接收到客户端连接 $client 后就交给由子进程进行后续的处理了,在这个例子只举例了单进程的模式。
页: [1]
查看完整版本: 一直让 PHP 程序员懵逼的同步阻塞异步非阻塞,终于搞明白了