マルチスレッドキャッシュクラッシュによるget_posts()の代替


8

私は複数のスレッドを作成するためにpthreadを使用しています。これらの各スレッドは、ある時点で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

注意してください、私は同じにする際にget_posts()通されていないコードセクションでの呼び出しを、私がクラッシュを持っていません。

さて、私の質問、pthreadスレッドget_posts()内から呼び出す方法は?それができない場合、代替手段は何ですか?

ありがとう。


更新

ここにサンプルコードがあります

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

これはクラッシュではなく、エラーです...エラーが発生しないようにコードを修正する必要があります。いずれにせよ、phpライブラリは常にマルチタスクで安全であるとは限らないため、問題はまったく異なるものにある可能性があります。
Mark Kaplun、2015

加えて、ミューテックスを使用する必要があるよりも「同時に」実行するために保護する必要があるコードがある場合、それはここでは範囲外です。
Mark Kaplun、2015

@MarkKaplun-ご協力ありがとうございます。ただし、「スレッド化されていないコードセクションで同じget_posts()呼び出しを行うと、クラッシュしない」と私が述べた点を逃したようです。だから私のget_posts($args)電話で問題はありません。さらに、この時点で保護する必要のあるコードはありません。私はWordPress DBからを読んでいるだけですget_posts($args)
Greeso

3
@MarkKaplun-どうしたの?なぜあなたはそんなにネガティブでアグレッシブなのですか?なぜ私はマルチタスクを理解していないと思い、pthreadを使用しないように勧めているのですか?たとえあなたが正しいとしても、私たちが理解していないことを試して、知識と限界を広げようとするのではないですか?また、このサイトでは、特定のことをどのように行うかわからない場合に質問することはしませんか?私は何もふりをしていません。エラーが発生しました。pthreadを使用していることが原因であることに気付き、解決策(セットアップまたはプログラミングの回避策)を求めています。自分からの建設的な答えを期待していた。
Greeso

2
WordPressがこのコードを壊す理由ではないことが本当にわかるまでは、話題になっています。
fuxia

回答:


2

質問には非常に多くの賛成票があるため、マルチスレッドの問題は回答の形式としては広すぎますが、ワードプレスAPIをマルチスレッドで使用してはいけない理由を説明しようと思います。

TL; DR-PHPはマルチスレッド対応であると想定されていません。問題はPHP自体ではなく、主にPHPが使用するライブラリです。このため、Apacheでマルチスレッド実行モードを使用ないことをお勧めしますが、理論上は多少高速になるはずです。基になるレイヤーがマルチスレッドに対応していないという問題に加えて、ワードプレスコアはマルチスレッドの最も基本的な要件に違反します。グローバルへの無料アクセスはありません。

マルチスレッド環境のグローバルの問題は何ですか?単純に見えるコードがあるとしましょう

function inc() {
  global $g;

  $g++;
}

これは1つのライナーにすぎませんが、CPUのアトミック操作ではなく、実際に実行するにはいくつかのマシンレベルの命令が必要です。何かのようなもの

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

ここinc()で、「同時に」呼び出す2つのスレッドABがあるとします(当然、CPUが1つだけの場合、同じようなものはありません)。$ gの初期値は0で、$の値はg両方のスレッドが終了した後?OSがマルチスレッドを処理する方法に依存します。いつスレッドを切り替えるかによって異なります。「古い」スタイルのOSでは、制御を奪うことができるAPIを呼び出すことによって宣言するのがスレッドの仕事でしたが、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はそれをしません。

地獄、ワードプレスはマルチプロセスでも安全ではありません。ほとんどの場合、DBスキーマは、実際の使用では異なるプロセスからの同じデータを変更する必要がないように構築されているため(別の投稿には異なる行があり、データを共有しないため)、それはなくなりますが、サイドバー/ウィジェットコードを使用して、2人の管理者がまったく同時に別のウィジェットを追加しようとするとどうなるかを想像してみてください。これには1つの特定のオプションの操作が必要になるため、最終結果は両方のウィジェットが追加されるか、どちらか一方のみになります。

マルチスレイディングに戻る。UNIXでは、Windowsとは異なり、スレッドの代わりにプロセスを生成する追加のコストはごくわずかです。そのため、wp_remote_get特別なURLを使用して追加の「スレッド」を呼び出すことは、マルチスレッドに関連するほとんどすべての落とし穴を回避するための非常に正当なことです。


これはよく説明されています。ありがとう。また、pthreadapacheで動作するためのサポートが削除されることもわかりました。pthreadを機能させるには、CLI環境内にある必要があります。私にはpthreadsが必要ですが、このソリューションはリリース後(つまり拡張機能)まで延期します。また、WordPressをCLI環境としてセットアップする必要があります(詳細はこちらwp-cli.org)。そうすることで、CLIからpthreads / WordPress環境を操作できるようになり、apacheなしでバックエンドで重い作業を行うことができます。もう一度お願いします。
Greeso

追加するために、pdbがdbに関連しない問題を処理するように制限します。そして、あなたの提案に従って、データベースの書き込みにはミューテックスを使用してください。
Greeso

@Greeso、Linuxのは、同時実行のニーズに対応するために複数のプロセスを使用して新しいプロセスを生成するように設計されましたが... pthreadsを使用したとして、本当に安全で早くである
マークKaplun
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.