由于这个问题有太多的赞成票,虽然多线程的问题对于一个答案的格式来说太广泛了,我将尝试解释为什么不应该以多线程的方式使用wordpress API。。。。
TL;PHP并没有被假定为支持多线程,问题不在于PHP本身,而主要在于它使用的库。这就是为什么建议not to use apache中的多线程执行模式,虽然理论上应该更快一些。为了解决底层不能支持多线程的问题,wordpress core违反了多线程的最基本要求——不能自由访问全局。
多线程环境中globals的问题是什么?让我们假设我们有看起来很天真的代码
function inc() {
global $g;
$g++;
}
虽然它只是一行程序,但它不是CPU的原子操作,需要几个机器级指令才能实际执行。比如
move $g to register D
increment register D
move register D to $g
现在我们假设有两个线程A B调用
inc()
在“同一时间”(显然,只有一个CPU时,不存在“同一时间”这样的事情),并且$g的初始值是0,那么在两个线程都完成后,$g的值是多少?这将取决于操作系统如何处理多线程,何时在线程之间切换。在“较旧”风格的操作系统中,线程的工作是通过调用API声明可以从中获取控制,但这会导致许多行为不良的进程锁定系统的问题,因此在“现代”操作系统中,操作系统在任何时候都可以控制。在现实生活中,代码的结果是$g的值为2,但也有以下可能性
在
move $g to register D
// value of D is 0
// OS stores the content of registers and switches to thread B
// B increments $g to 1 and finishes working
// OS restores content of registers to the context of thread A
// Value of register D is now 0
increment register D
move register D to $g
最终结果是$g的值为1。
显然,全局函数不是唯一的问题,处理输入和输出也是多线程问题的核心。
在正确的多线程代码中,使用锁/互斥体/信号量/管道/套接字。。。。序列化对此类全局资源的访问,以确保操作的结果是可预测的。Wordpress不这样做。
该死,wordpress甚至都不是多进程安全的。大多数情况下,它都不会受到影响,因为DB模式的构建方式在现实生活中可以避免修改来自不同进程的相同数据(不同的帖子有不同的行,不共享数据),但请查看侧栏/小部件代码,并尝试想象如果两个管理员尝试在完全相同的时间添加不同的小部件会发生什么。由于这将需要操纵一个特定的选项,最终结果可以是添加两个小部件,也可以是其中一个。
返回多线程。在unix中,与windows不同,生成进程而不是线程的额外成本可以忽略不计,因此使用wp_remote_get
使用一些特殊的url来调用额外的“线程”是一件非常合理的事情,可以避免几乎所有与多线程相关的陷阱。