PHP中的并发编程初探:多线程、协程等

说白了,PHP中的并发方式只有三种:多线程、协程、异步。
选择对了可以事半功倍,但选择错了……说实话,这真是一个陷阱。

多线程适用于CPU工作量较大的场景。
去年我们跑电商平台项目,直接使用PThreads进行3 000并发用户的压力测试。
结果,线程被锁定并陷入死锁——行话中称为雪崩效应。
事实上,前面的一个小延迟就导致了整个后面的事情。
然而,有一个关键细节。
例如,使用pthread_mutex_t进行加锁时,必须注意PThreads在PHP7 .2 之后已经不太流行了。
如今,所有基于 CSP 的替代方案都已被使用。
不要愚蠢地继承Thread类。

协程是 I/O 密集型任务的神器。
我们接手了一个微信长连接服务。
改用Swoole协程后,百万并发直接跑掉,切换开销比线程小一百倍。
但还有一点就是,我一开始以为协程可以随意扔掉资源,后来发现错了。
一个未释放的文件句柄会拖累整个过程——我必须学习Java使用try-with-resources来自动回收。
还有另一个关键细节。
协程的共享数据必须加锁,否则数据竞争会爆发。
想想看,线程安全都处理不好,更何况是这么轻量级的单元。

异步编程是最简单、最粗暴的。
使用Swoole作为HTTP服务器,on('request',...)这几行代码,非阻塞IO,直接最大化吞吐量。
但说实话,这很令人困惑。
回调被嵌套并写入面条代码中,这让我在调试时发疯。
我们有一个项目,使用 Promise 来重构异步代码。
结果Promise链嵌套了五层,最后我们改用async/await来搞定。
等等,还有一件事。
异步编程严重依赖事件循环。
如果事件循环被卡住,整个系统就会瘫痪。
想想浏览器卡住的时候的体验……
最后说实话,业务需求才是王道。
不要只关注技术是否新颖。
就看CPU流行还是I/O主流。
比如做定时任务的时候,不用理会异步任务,直接使用多进程; 做API网关的时候,不用理会多线程,直接用协程就可以了。
但我认为值得先尝试构建一个最小可行版本,例如使用协程来运行简单的长期连接服务,然后测试性能。

什么是多线程技术

嗯...多线程...2 02 2 年的情况...后来才意识到...这个东西很重要。

它是一个程序...它可以同时做几件事...不是一行到最后...一行叫做线程...想一想...计算机的CPU很忙...总是做一件事...不用等...2 02 2 年的手机性能很差...特别卡...多线程解决了这个问题...让CPU同时做几件事...提高效率...想一想...可以同时处理多少件事时间...也许我有偏见...但它提高了速度。

好处很多...想一想...资源占用...比如2 02 2 年的那台服务器...要处理多少个请求...多少个请求...多个线程可以同时处理...节能快...程序响应...一个线程卡住...比如等待网络...另一个还可以工作。
.. 用户不必等待... 2 02 2 年那个大城市... 用户体验有多大取决于这个... 简化编程模型... 把大问题分解成小问题... 2 02 2 年那个程序员... 会省事... 想一想... 可以节省多少代码... 多少钱...
应用场景更广泛... 看看... 2 02 2 年那个淘宝... 多少并发用户... 多少... 是否应该使用多线程... 数据库管理还使用... GUI应用程序...就像2 02 2 年的Windows...你点击鼠标...有多少线程在运行...并行计算...AI就是这样训练的...多少数据...这么多线程...想一想...可以节省多少计算能力...
总之...多线程技术...正在让计算机更高效地工作...2 02 2 年的情况...特别实用...

刨析swoole开发功能的多线程与多进程调度方式

哎呀,Swoole的多线程多进程,我在做项目的时候也遇到了弊端。
让我跟你谈谈。

前年,我在上海做一个电商闪购系统,服务器崩溃了两次。
经过调查发现PHP的GIL受到了限制。
在运行多线程计算任务时,CPU并不能完全满足。
切换到多进程后,四个核心运行速度快了很多,问题就解决了。

看吧,多线程很方便。
共享内存意味着数据可以更快地传输。
我有一个项目,处理订单信息,使用多线程传输数据。
它不需要任何IPC,直接写入共享内存。
真的很快。
但后来发现是某个线程损坏了,锁处理不当导致整个系统卡住了。
这很悲伤。
因此,在使用多线程时,你必须非常小心锁、互斥锁、读写锁,这就像一场战争。

多次手术更安全。
去年我们在北京开发了一个直播服务。
每个用户都有一个流程,谁断开电话,对其他人没有影响。
进程间通信需要用到IPC、消息队列、共享内存等,有点复杂,但是至少有一个进程结束了,其他的就没事了。
我记得我是用消息队列来传输数据的。
忙了好久,队列已经排满了它走了,却被卡住了。
最后我加了超时再试,终于解决了。

所以你看,不同场景下用什么:
共享数据很多吗?比如缓存同步等等,多线程方便。
任务是独立的,需要分开吗?例如,当运行任务队列时,多个进程被冻结。
CPU 工作量过多?允许多进程、多核CPU运行。
有大量 I/O 而 CPU 空闲?多线程还可以提高性能,例如在等待网络响应时。

Swool 目前正在研究协程和用户模式线程池。
我认为这是正确的方向。
不管怎样,在我后来的新项目中,我基本上都使用了协程,所以我不必担心CPU和I/O。
但这东西需要学习和了解基础知识,而不是盲目使用。
你怎么认为?