問題描述

我使用 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:devwordpresswp-includescache.php on line 123

請注意,當我在沒有執行緒的程式碼段中進行相同的 get_posts()呼叫時,我沒有崩潰。

現在,我的問題,如何從一個 pthread 執行緒中呼叫 get_posts()?如果我不能這樣做,還有什麼可選擇的?

謝謝。


Update

這是示例程式碼

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();
}

最佳解決方案

既然有這麼多的提升這個問題,雖然多執行緒的問題對於一個答案的格式來說太廣泛了,但我將嘗試解釋為什麼你不應該以多執行緒方式使用 wordpress API ….

長話短說 – PHP 不被假定為多執行緒準備就緒,問題不是 PHP 本身,而是主要是它使用的庫。這就是為什麼建議在 apache 中不要使用多執行緒執行模式,但在理論上應該會更快一些。為了增加底層不是多執行緒準備就緒的問題,wordpress 核心違反了多執行緒最基本的要求 – 不能免費訪問全域性變數。

多執行緒環境中全域性變數的問題是什麼?讓我們假設我們有天真的尋找程式碼

function inc() {
  global $g;

  $g++;
}

雖然它只是一個內襯,但它不是 CPU 的原子操作,它需要幾個機器級指令來動態執行它。就像是

move $g to register D
increment register D
move register D to $g

現在假設我們有兩個執行緒 AB,在”same time” 呼叫 inc()(顯然只有一個 CPU 沒有同一時間沒有這樣的事情),並且 $ g 的初始值為 0,那麼 $ g 的值將是兩個執行緒完成了?它將取決於作業系統如何處理多執行緒,何時線上程之間切換。在”older” 樣式作業系統中,執行緒的工作是透過呼叫 API 來宣告控制,但是導致在”modern” OS 中鎖定系統的不良行為流程的許多問題,OS 隨時可以控制感覺好像在現實生活中,程式碼的結果將是 $ g 的值為 2,但是還有以下可能性

在 A 的上下文中

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 。

顯然,全域性變數不是唯一的問題,處理輸入和輸出也是解密問題的核心。

在正確的多執行緒程式碼中,您可以使用 lock /mutex /semaphore /pipe /socket …. 來序列化對這些全域性資源的訪問,以確保對該操作有可預測的結果。 WordPress 不這樣做

地獄,wordpress 甚至不是多程式安全。大多數時候它被忽略,因為 DB 模式是以一種在現實生活中使用的方式構建的,從而阻止了從不同程式修改相同資料的需要 (不同的帖子有不同的行,不共享資料),但是看看側邊欄/小工具程式碼,並嘗試想象如果兩個管理員嘗試在完全相同的時間新增一個不同的小工具會發生什麼。因為這將需要操縱一個特定的選項,所以最終的結果可以是新增的小工具,也可以只是其中的一個。

回到多執行緒。在 unix 中,與 windows 不同,產生一個程式而不是執行緒的額外成本是可忽略的,因此使用 wp_remote_get 與一些特殊的 url 來呼叫額外的”thread” 是一個非常合法的事情,並避免幾乎所有與多執行緒相關的陷阱。

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。