問題描述
我使用 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 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。