Da die Frage so viele positive Stimmen enthält, obwohl die Probleme des Multithreading für ein Antwortformat einfach zu weit gefasst sind, werde ich versuchen zu erklären, warum Sie die WordPress-API nicht auf Multithread-Weise verwenden sollten.
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 er theoretisch etwas schneller sein sollte. Um das Problem zu verstärken, dass die zugrunde liegende Ebene nicht Multithread-fähig ist, verstößt der WordPress-Kern gegen die grundlegendste Anforderung von Multithread - kein freier 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 sich nur um einen Einzeiler handelt, handelt es sich nicht um eine atomare Operation für die CPU, und es sind mehrere Anweisungen auf Maschinenebene erforderlich, um sie tatsächlich auszuführen. Etwas wie
move $g to register D
increment register D
move register D to $g
Nehmen wir nun an, wir haben zwei Threads AB, inc()
die "zur gleichen Zeit" aufrufen (offensichtlich gibt es bei nur einer CPU nicht die gleiche Zeit) und dass der Anfangswert von $ g 0 ist, was der Wert von $ wäre g nachdem beide Threads fertig sind? Dies hängt davon ab, wie das Betriebssystem mit Multithreading umgeht und wann es zwischen Threads wechselt. In "älteren" Betriebssystemen war es die Aufgabe des Threads, durch Aufrufen einer API zu deklarieren, dass die Steuerung von ihr übernommen werden kann. Dies führt jedoch zu vielen Problemen mit Prozessen, die sich schlecht verhalten und das System dafür in "modernen" Betriebssystemen sperren, die das Betriebssystem übernimmt 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 Kontext von 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
Das Endergebnis ist, dass $ g den Wert 1 hat.
Offensichtlich sind Globale nicht das einzige Problem, und die Behandlung von Ein- und Ausgängen ist auch ein Kern für Mutithreading-Probleme.
Im richtigen Multithreading-Code verwenden Sie lock / mutex / semaphore / pipe / socket ...., um den Zugriff auf solche globalen Ressourcen zu serialisieren und sicherzustellen, dass die Operation ein vorhersehbares Ergebnis liefert. Wordpress macht das nicht.
Zur Hölle, WordPress ist nicht einmal mehrprozesssicher. Meistens kommt es damit durch, weil das DB-Schema so aufgebaut ist, dass im realen Leben nicht die gleichen Daten aus verschiedenen Prozessen geändert werden müssen (verschiedene Posts haben unterschiedliche Zeilen und teilen keine Daten) den Code der Seitenleiste / der Widgets und versuchen Sie sich vorzustellen, was passieren wird, wenn zwei Administratoren versuchen würden, genau zur gleichen Zeit ein anderes Widget hinzuzufügen. Da dies die Manipulation einer bestimmten Option erfordert, können entweder beide Widgets oder nur eines davon hinzugefügt werden.
Zurück zum Multithrading. Unter Unix sind im Gegensatz zu Windows die zusätzlichen Kosten für das Laichen eines Prozesses anstelle eines Threads vernachlässigbar. Daher ist die Verwendung wp_remote_get
einer speziellen URL zum Aufrufen eines zusätzlichen "Threads" eine sehr legitime Maßnahme, um fast alle mit Multithreading verbundenen Fallstricke zu vermeiden.