由于多线程缓存崩溃,GET_POST()的替代方法

时间:2015-12-24 作者:Greeso

我正在使用pthreads 创建多个线程。这些线程中的每一个都试图使用get_posts() 具体如下:

$args = array(
    \'post_type\' => \'post\',
    \'post_status\' => \'any\'
);

$posts_list = get_posts($args);
然而,我最终遇到了以下崩溃:

HP Fatal error:  Call to a member function get() on a non-object in C:\\dev\\wordpress\\wp-includes\\cache.php on line 123
PLEASE NOTE 当我做同样的get_posts() 在没有线程的代码段中调用,我没有崩溃。

现在,我的问题是,如何打电话get_posts() 从内部pthread 线如果我不能做到这一点,还有什么选择?

谢谢

更新这里是示例代码

class My_Thread extends Thread {

    public function run() {

        /* DO SOME STUFF HERE */

        $args = array(
            \'post_type\' => \'post\',
            \'post_status\' => \'any\'
        );

        $posts_list = get_posts($args); // <------ This is causing the crash
    }
}

// Create a array
$threads = array();

//Iniciate Miltiple Thread
foreach ( range("A", "C") as $i ) {
    $threads[] = new My_Thread($i);
}

// Start The Threads
foreach ($threads as $thread) {
    $thread->start();
}

1 个回复
最合适的回答,由SO网友:Mark Kaplun 整理而成

由于这个问题有太多的赞成票,虽然多线程的问题对于一个答案的格式来说太广泛了,我将尝试解释为什么不应该以多线程的方式使用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来调用额外的“线程”是一件非常合理的事情,可以避免几乎所有与多线程相关的陷阱。

相关推荐

WordPress and multithreading

我正在开发一个插件。我创建了一个API,可以读取和写入DB中的自定义表。可以从N个客户端同时调用此API(这确实发生了)。我注意到在这种情况下会出现问题。举一个具体的例子:if (is_null($wpdb->get_var(\"SELECT column FROM my_table_name WHERE condition\"))) { // branch 1 } else { // branch 2 } 在分支1中,我天真地假设从