Alternative zu get_posts () wegen Multithreading-Cache-Crash

Ich benutze Pthreads, um mehrere Threads zu erstellen. Jeder dieser Threads an einem Punkt versucht, get_posts() wie folgt zu verwenden:

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

Allerdings habe ich folgenden Crash:

 HP Fatal error: Call to a member function get() on a non-object in C:\dev\wordpress\wp-includes\cache.php on line 123 

BITTE get_posts() wenn ich denselben Aufruf get_posts() in einem Codeabschnitt mache, der nicht mit Threads versehen ist, habe ich keinen Absturz.

Nun, meine Frage, wie get_posts() aus einem Pthread- Thread heraus aufgerufen wird? Und wenn ich das nicht kann, was ist die Alternative?

Vielen Dank.


Aktualisieren

Hier ist ein Beispielcode

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

Solutions Collecting From Web of "Alternative zu get_posts () wegen Multithreading-Cache-Crash"

Da es so viele Upvotes zu der Frage gibt, obwohl die Probleme des Multithreading für ein Format einer Antwort einfach zu weit sind, werde ich versuchen zu erklären, warum man die wordpress API nicht auf Multithread-Art benutzen sollte ….

TL; DR – PHP wird nicht als Multithreading-fähig angenommen, das Problem ist nicht PHP selbst, sondern hauptsächlich die verwendeten Bibliotheken. Aus diesem Grund wird empfohlen , den Multithread-Ausführungsmodus in Apache nicht zu verwenden, obwohl es theoretisch etwas schneller sein sollte. Um das Problem zu beheben, dass die zugrunde liegende Ebene nicht multithread-fähig ist, verletzt wordpress core die grundlegendste Anforderung von Multithread – keinen freien Zugriff auf Globals.

Was ist das Problem mit Globals in Multithread-Umgebungen? Nehmen wir an, wir haben den naiv aussehenden Code

 function inc() { global $g; $g++; } 

Obwohl es nur ein einzelner Liner ist, handelt es sich nicht um eine atomare Operation für die CPU, und es bedarf mehrerer Befehle auf Maschinenebene, um sie tatsächlich auszuführen. Etwas wie

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

Nun nehmen wir an, wir haben zwei Threads AB, die inc() zur “gleichen Zeit” aufrufen (offensichtlich mit nur einer CPU gibt es keine solche Zeit), und dass der Anfangswert von $ g 0 ist, was wäre das Wert von $ g, nachdem beide Threads beendet wurden? Es hängt davon ab, wie das Betriebssystem Multithreading behandelt, wann es zwischen Threads wechselt. Bei “älteren” Betriebssystemen war es die Aufgabe des Threads, durch Aufrufen einer API zu deklarieren, dass eine Steuerung daraus abgeleitet werden kann, was jedoch zu vielen Problemen mit errorshaften processen führt, die das System dafür im “modernen” Betriebssystem sperren Kontrolle, wann immer es sich anfühlt. Im wirklichen Leben wird das Ergebnis des Codes sein, dass $ g einen Wert von 2 hat, aber es gibt auch die folgende Möglichkeit

Im Zusammenhang mit 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 

Endergebnis ist, dass $ g den Wert 1 hat.

Offensichtlich sind Globals nicht das einzige Problem, und die Handhabung von Eingaben und Ausgaben ist auch ein core für Probleme mit dem Multithreading.

Im richtigen Multithreading-Code verwenden Sie lock / mutex / semaphore / pipe / socket …. um den Zugriff auf solche globalen Ressourcen zu serialisieren, um sicherzustellen, dass das Ergebnis vorhersehbar ist. WordPress mache das nicht.

Hell, WordPress ist nicht einmal multiprozesssicher. Die meiste Zeit kommt es damit klar, weil das DB-Schema so aufgebaut ist, dass es im realen Leben verhindert, dass dieselben Daten von verschiedenen processen modifiziert werden müssen (verschiedene Beiträge haben unterschiedliche Zeilen und teilen keine Daten), aber schauen Sie sich an die Sidebar / Widgets Code und versuchen Sie sich vorzustellen, was passiert, wenn zwei Admins versuchen würden, gleichzeitig ein anderes Widget hinzuzufügen. Da dies die Manipulation einer bestimmten Option erfordert, kann das Endergebnis entweder beide Widgets oder nur eines davon sein.

Zurück zum Multithrading. Anders als bei Windows sind die zusätzlichen Kosten für das wp_remote_get eines processes anstelle von thread vernachlässigbar. Daher ist die Verwendung von wp_remote_get mit einer speziellen URL zum Aufrufen von zusätzlichen ” wp_remote_get ” eine sehr legitime Sache und vermeidet fast alle Fallstricke, die mit Multithreading verbunden sind.