Hat PHP Threading?

130

Ich habe dieses PECL-Paket namens threads gefunden , aber es gibt noch keine Version. Und auf der PHP-Website wird nichts angezeigt.

Thomas Owens
quelle
Weiß jemand, ob this ( pcntl_fork()) funktioniert, wenn es von Apache aufgerufen wird?
Josh K
Das ist unglaublich alt, aber ich habe eine Antwort, die tatsächlich Threading in PHP bietet (siehe unten für Links).
Alec Gorge
Sie empfehlen, fork nicht von einer Serverumgebung aus aufzurufen. Ich beschuldige sie nicht. Pcntl_fork scheint jedoch die beste Lösung für das Threading von PHP zu sein.
just_wes
Ja, Sie sollten keinen Apache2-PHP-Prozess verzweigen müssen.
Andho
2
Verwenden Sie Pthreads funktioniert wie Charme
Baba

Antworten:

40

Es ist nichts verfügbar, von dem ich weiß. Das nächstbeste wäre, einfach ein Skript ein anderes über die CLI ausführen zu lassen, aber das ist ein bisschen rudimentär. Je nachdem, was Sie versuchen und wie komplex es ist, kann dies eine Option sein oder auch nicht.

Wilco
quelle
1
Das ist was ich dachte. Ich sah eine Reihe älterer Postings, die Nein sagten, und nichts auf php.net, also war dies mein Gedanke. Vielen Dank für die Bestätigung.
Thomas Owens
2
Ja, dieses PECL-Paket ist eine Art Scherz - ich bin auch darauf gestoßen, aber es ist nie etwas daraus geworden.
Wilco
180

Aus dem PHP-Handbuch für die Erweiterung pthreads :

pthreads ist eine objektorientierte API, die User-Land-Multithreading in PHP ermöglicht. Es enthält alle Tools, die Sie zum Erstellen von Multithread-Anwendungen für das Web oder die Konsole benötigen. PHP-Anwendungen können Threads, Worker und Stackables erstellen, lesen, schreiben, ausführen und synchronisieren.

So unglaublich das auch klingt, es ist völlig wahr. Heute kann PHP Multithreading für diejenigen, die es ausprobieren möchten.

In der ersten Version von PHP4, 22. Mai 2000, wurde PHP mit einer thread-sicheren Architektur ausgeliefert - eine Möglichkeit, mehrere Instanzen seines Interpreters in separaten Threads in SAPI-Umgebungen (Server API) mit mehreren Threads auszuführen. In den letzten 13 Jahren wurde das Design dieser Architektur beibehalten und weiterentwickelt: Seitdem wird sie auf den weltweit größten Websites in der Produktion eingesetzt.

Das Einfädeln in Benutzerland war für das PHP-Team nie ein Problem und ist es auch heute noch. Sie sollten verstehen, dass es in der Welt, in der PHP geschäftlich tätig ist, bereits eine definierte Skalierungsmethode gibt - Hardware hinzufügen. Im Laufe der vielen Jahre, in denen PHP existiert, ist Hardware immer billiger geworden, und so wurde dies für das PHP-Team immer weniger zu einem Problem. Während es billiger wurde, wurde es auch viel leistungsfähiger; Heutzutage verfügen unsere Mobiltelefone und Tablets über Dual- und Quad-Core-Architekturen und viel RAM. Unsere Desktops und Server verfügen normalerweise über 8 oder 16 Kerne, 16 und 32 Gigabyte RAM, obwohl wir möglicherweise nicht immer über zwei verfügen können Innerhalb des Budgets und mit zwei Desktops ist es für die meisten von uns selten nützlich.

Darüber hinaus wurde PHP für den Nicht-Programmierer geschrieben, es ist viele Hobbyisten Muttersprache. Der Grund, warum PHP so einfach zu übernehmen ist, ist, dass es eine leicht zu erlernende und zu schreibende Sprache ist. Der Grund, warum PHP heute so zuverlässig ist, liegt in der enormen Arbeit, die in das Design fließt, und in jeder einzelnen Entscheidung der PHP-Gruppe. Seine Zuverlässigkeit und Größe halten es nach all den Jahren im Rampenlicht; wo seine Rivalen auf Zeit oder Druck gefallen sind.

Multithread-Programmierung ist für die meisten nicht einfach, selbst mit der kohärentesten und zuverlässigsten API gibt es verschiedene Dinge zu bedenken und viele Missverständnisse. Die PHP-Gruppe möchte nicht, dass User Land Multithreading ein Kernmerkmal ist, es wurde nie ernsthaft darauf geachtet - und das zu Recht. PHP sollte nicht für alle komplex sein.

Alles in allem gibt es immer noch Vorteile, wenn PHP seine produktionsfertigen und getesteten Funktionen nutzen kann, um das Beste aus dem herauszuholen, was wir haben, wenn das Hinzufügen von mehr nicht immer eine Option ist und für viele von Aufgaben wird nie wirklich benötigt.

pthreads bietet für diejenigen, die es erkunden möchten, eine API, mit der ein Benutzer PHP-Anwendungen mit mehreren Threads ausführen kann. Die API ist in Arbeit und wird als Beta-Level für Stabilität und Vollständigkeit bezeichnet.

Es ist allgemein bekannt, dass einige der von PHP verwendeten Bibliotheken nicht threadsicher sind. Dem Programmierer sollte klar sein, dass pthreads dies nicht ändern können und nicht versuchen, es zu versuchen. Jede Bibliothek, die threadsicher ist, kann jedoch verwendet werden, wie bei jedem anderen threadsicheren Setup des Interpreters.

pthreads verwendet Posix-Threads (auch unter Windows). Der Programmierer erstellt echte Ausführungsthreads. Damit diese Threads jedoch nützlich sind, müssen sie sich mit PHP auskennen, um Benutzercode ausführen, Variablen gemeinsam nutzen und nützliche Kommunikationsmittel zulassen zu können (Synchronisation). Daher wird jeder Thread mit einer Instanz des Interpreters erstellt. Der Interpreter ist jedoch konstruktionsbedingt von allen anderen Instanzen des Interpreters isoliert - genau wie Server-API-Umgebungen mit mehreren Threads. pthreads versucht, die Lücke auf gesunde und sichere Weise zu schließen. Viele der Bedenken des Programmierers von Threads in C sind für den Programmierer von Pthreads einfach nicht vorhanden. Pthreads sind von Natur aus Kopie beim Lesen und Kopie beim Schreiben (RAM ist billig), sodass keine zwei Instanzen jemals dieselben physischen Daten manipulieren , aber beide können Daten in einem anderen Thread beeinflussen.

Warum beim Lesen kopieren und beim Schreiben kopieren:

public function run() {
    ...
    (1) $this->data = $data;
    ...
    (2) $this->other = someOperation($this->data);
    ...
}

(3) echo preg_match($pattern, $replace, $thread->data);

(1) Während eine Lese- und Schreibsperre für den Objektdatenspeicher von pthreads gehalten wird, werden Daten von ihrem ursprünglichen Speicherort in den Objektspeicher kopiert. pthreads passt den Refcount der Variablen nicht an. Zend kann die Originaldaten freigeben, wenn keine weiteren Verweise darauf vorhanden sind.

(2) Das Argument zu someOperation verweist auf den Objektspeicher, die gespeicherten Originaldaten, die selbst eine Kopie des Ergebnisses von (1) sind, werden für die Engine erneut in einen zval-Container kopiert, während dabei eine Lesesperre gehalten wird Im Objektspeicher wird die Sperre aufgehoben und die Engine kann die Funktion ausführen. Wenn das zval erstellt wird, hat es eine Refcount von 0, sodass die Engine die Kopie nach Abschluss des Vorgangs freigeben kann, da keine anderen Verweise darauf vorhanden sind.

(3) Das letzte Argument für preg_match verweist auf den Datenspeicher, eine Lesesperre wird erhalten, der Datensatz in (1) wird erneut mit einem Refcount von 0 in ein zval kopiert. Die Sperre wird aufgehoben. Der Aufruf von preg_match wird ausgeführt eine Kopie der Daten, dh selbst eine Kopie der Originaldaten.

Sachen zu wissen:

  • Die Hash-Tabelle des Objektspeichers, in der Daten threadsicher gespeichert werden,
    basiert auf der von Zend mit PHP gelieferten TsHashTable.

  • Der Objektspeicher verfügt über eine Lese- und Schreibsperre. Für die TsHashTable wird eine zusätzliche Zugriffssperre bereitgestellt, sodass pthreads bei Bedarf (und zwar var_dump / print_r, direkter Zugriff auf Eigenschaften, auf die die PHP-Engine verweisen möchte) die TsHashTable manipulieren können außerhalb der definierten API.

  • Die Sperren werden nur gehalten, während die Kopiervorgänge ausgeführt werden. Wenn die Kopien erstellt wurden, werden die Sperren in einer sinnvollen Reihenfolge freigegeben.

Das heisst:

  • Wenn ein Schreibvorgang ausgeführt wird, wird nicht nur eine Lese- und Schreibsperre gehalten, sondern auch eine zusätzliche Zugriffssperre. Die Tabelle selbst ist gesperrt. Es gibt keine Möglichkeit, wie ein anderer Kontext sie sperren, lesen, schreiben oder beeinflussen kann.

  • Wenn ein Lesevorgang stattfindet, wird nicht nur die Lesesperre gehalten, sondern auch die zusätzliche Zugriffssperre, und die Tabelle wird erneut gesperrt.

Keine zwei Kontexte können physisch oder gleichzeitig auf dieselben Daten aus dem Objektspeicher zugreifen, aber Schreibvorgänge, die in einem beliebigen Kontext mit einer Referenz ausgeführt werden, wirken sich auf die Daten aus, die in einem beliebigen Kontext mit einer Referenz gelesen werden.

Dies wird nichts Architektur geteilt und der einzige Weg zu existieren ist das Nebeneinander. Diejenigen, die ein bisschen versiert sind, werden sehen, dass hier viel kopiert wird, und sie werden sich fragen, ob das eine gute Sache ist. Innerhalb einer dynamischen Laufzeit wird ziemlich viel kopiert, das ist die Dynamik einer dynamischen Sprache. pthreads wird auf Objektebene implementiert, da eine gute Kontrolle über ein Objekt erzielt werden kann, Methoden - der vom Programmierer ausgeführte Code - jedoch einen anderen Kontext haben, der frei von Sperren und Kopien ist - den lokalen Methodenbereich. Der Objektbereich im Fall eines pthreads-Objekts sollte als eine Möglichkeit behandelt werden, Daten zwischen Kontexten auszutauschen, das ist der Zweck. In diesem Sinne können Sie Techniken anwenden, um das Sperren des Objektspeichers zu vermeiden, sofern dies nicht erforderlich ist.

Die meisten für PHP verfügbaren Bibliotheken und Erweiterungen sind Thin Wrapper für Drittanbieter. Die PHP-Kernfunktionalität ist bis zu einem gewissen Grad dieselbe. pthreads ist kein dünner Wrapper um Posix Threads. Es ist eine Threading-API, die auf Posix-Threads basiert. Es macht keinen Sinn, Threads in PHP zu implementieren, die die Benutzer nicht verstehen oder nicht verwenden können. Es gibt keinen Grund, warum eine Person, die nicht weiß, was ein Mutex ist oder tut, nicht in der Lage sein sollte, alles zu nutzen, was sie hat, sowohl in Bezug auf Fähigkeiten als auch in Bezug auf Ressourcen. Ein Objekt funktioniert wie ein Objekt, aber wo immer zwei Kontexte kollidieren würden, bieten pthreads Stabilität und Sicherheit.

Jeder, der in Java gearbeitet hat, wird die Ähnlichkeiten zwischen einem pthreads-Objekt und dem Threading in Java erkennen. Dieselben Personen haben zweifellos einen Fehler namens ConcurrentModificationException gesehen - da es sich um einen Fehler handelt, der von der Java-Laufzeit ausgelöst wird, wenn zwei Threads dieselben physischen Daten schreiben gleichzeitig. Ich verstehe, warum es existiert, aber es verblüfft mich, dass mit so billigen Ressourcen wie ihnen die Laufzeit die Parallelität genau zu dem Zeitpunkt erkennen kann, zu dem die Sicherheit für den Benutzer erreicht werden kann, den er wählt Wirf zur Laufzeit einen möglicherweise schwerwiegenden Fehler aus, anstatt die Ausführung und den Zugriff auf die Daten zu verwalten.

Solche dummen Fehler werden von pthreads nicht ausgegeben. Die API wurde geschrieben, um das Threading so stabil und kompatibel wie möglich zu machen, glaube ich.

Multithreading ist nicht mit der Verwendung einer neuen Datenbank vergleichbar. Achten Sie besonders auf jedes Wort im Handbuch und auf Beispiele, die mit pthreads geliefert werden.

Zuletzt aus dem PHP-Handbuch:

pthreads war und ist ein Experiment mit ziemlich guten Ergebnissen. Alle Einschränkungen oder Funktionen können sich jederzeit ändern. das ist die Natur des Experimentierens. Die Einschränkungen, die häufig durch die Implementierung auferlegt werden, bestehen aus gutem Grund. Das Ziel von pthreads ist es, eine brauchbare Lösung für Multitasking in PHP auf jeder Ebene bereitzustellen. In der Umgebung, die pthreads ausführt, sind einige Einschränkungen und Einschränkungen erforderlich, um eine stabile Umgebung bereitzustellen.

Joe Watkins
quelle
14
Völliger Unsinn.
Joe Watkins
7
@GeoC. Ich bin mir nicht mal sicher, worum es hier geht, das ist nur eine Menge Kauderwelsch, und Sie geben keine logischen oder sonstigen Gründe an , warum Sie mit keinen Argumenten einverstanden sind (von denen ich in der Post keine wirklich sehen kann). .
Jimbo
13
@Tudor Ich glaube nicht, dass du wirklich weißt, wovon du sprichst, also bin ich glücklich, dich zu ignorieren.
Joe Watkins
4
@Tudor - Viele Wissenschaftler haben den Sinn von etwas Neuem in ihrer Branche oder etwas Nützlichem nicht "gesehen". Die Geschichte hat gezeigt, dass Menschen wie Sie meistens einfach falsch liegen, das ist eine Tatsache. Genauso wie es eine Tatsache ist, dass alles, was Sie hier geschrieben haben, mangels eines besseren Wortes Kot ist. Ich empfehle dringend, unter Berücksichtigung aller positiven Aspekte nicht an Themen teilzunehmen, von denen Sie nichts wissen (dies ist eines).
NB
12
Lustige Sache. Joe Watkins ist der Autor von Pthreads, und dennoch versucht Tudor, ihm das Gegenteil zu beweisen.
Hristo Valkanov
48

Hier ist ein Beispiel dafür, was Wilco vorgeschlagen hat:

$cmd = 'nohup nice -n 10 /usr/bin/php -c /path/to/php.ini -f /path/to/php/file.php action=generate var1_id=23 var2_id=35 gen_id=535 > /path/to/log/file.log & echo $!';
$pid = shell_exec($cmd);

Grundsätzlich führt dies das PHP-Skript in der Befehlszeile aus, gibt jedoch sofort die PID zurück und wird dann im Hintergrund ausgeführt. (Das echo $! Stellt sicher, dass nichts anderes als die PID zurückgegeben wird.) Auf diese Weise kann Ihr PHP-Skript fortgesetzt oder beendet werden, wenn Sie möchten. Wenn ich dies verwendet habe, habe ich den Benutzer auf eine andere Seite umgeleitet, auf der alle 5 bis 60 Sekunden ein AJAX-Aufruf durchgeführt wird, um zu überprüfen, ob der Bericht noch ausgeführt wird. (Ich habe eine Tabelle zum Speichern der gen_id und des Benutzers, auf den sie sich bezieht.) Das Überprüfungsskript führt Folgendes aus:

exec('ps ' . $pid , $processState);
if (count($processState) < 2) {
     // less than 2 rows in the ps, therefore report is complete
}

Es gibt hier einen kurzen Beitrag zu dieser Technik: http://nsaunders.wordpress.com/2007/01/12/running-a-background-process-in-php/

Darryl Hein
quelle
Ich habe ein kleines Problem. Wie überprüfst du den Status des Hintergrundprozesses? u kann mich aufklären
schlaue
25

Kurz gesagt: Ja, es gibt Multithreading in PHP, aber Sie sollten stattdessen Multiprocessing verwenden.

Hintergrundinformationen: Threads vs. Prozesse

Es gibt immer ein bisschen Verwirrung über die Unterscheidung von Threads und Prozessen, daher werde ich beide kurz beschreiben:

  • Ein Thread ist eine Folge von Befehlen, die die CPU verarbeitet. Die einzigen Daten, aus denen es besteht, sind Programmprogrammzähler. Jeder CPU-Kern verarbeitet jeweils nur einen Thread, kann jedoch über die Zeitplanung zwischen der Ausführung verschiedener Threads wechseln.
  • Ein Prozess besteht aus einer Reihe gemeinsam genutzter Ressourcen. Das heißt, es besteht aus einem Teil des Speichers, Variablen, Objektinstanzen, Dateihandles, Mutexen, Datenbankverbindungen usw. Jeder Prozess enthält auch einen oder mehrere Threads. Alle Threads desselben Prozesses teilen sich ihre Ressourcen, sodass Sie eine Variable in einem Thread verwenden können, den Sie in einem anderen erstellt haben. Wenn diese Threads Teil von zwei verschiedenen Prozessen sind, können sie nicht direkt auf die Ressourcen des jeweils anderen zugreifen. In diesem Fall benötigen Sie eine prozessübergreifende Kommunikation über z. B. Pipes, Dateien, Sockets ...

Mehrfachverarbeitung

Sie können paralleles Rechnen erreichen, indem Sie mit PHP neue Prozesse erstellen (die auch einen neuen Thread enthalten). Wenn Ihre Threads nicht viel Kommunikation oder Synchronisation benötigen, haben Sie die Wahl, da die Prozesse isoliert sind und die Arbeit des anderen nicht beeinträchtigen können. Selbst wenn einer abstürzt, geht das die anderen nicht an. Wenn Sie viel Kommunikation benötigen, sollten Sie unter "Multithreading" weiterlesen oder - leider - eine andere Programmiersprache verwenden, da die Kommunikation und Synchronisation zwischen Prozessen viel Teint mit sich bringt.

In PHP gibt es zwei Möglichkeiten, einen neuen Prozess zu erstellen:

Lassen Sie das Betriebssystem dies für Sie tun : Sie können Ihr Betriebssystem anweisen, einen neuen Prozess zu erstellen und ein neues (oder dasselbe) PHP-Skript darin auszuführen.

  • Für Linux können Sie Folgendes verwenden oder die Antwort von Darryl Hein in Betracht ziehen :

    $cmd = 'nice php script.php 2>&1 & echo $!';
    pclose(popen($cmd, 'r'));
  • Für Windows können Sie Folgendes verwenden:

    $cmd = 'start "processname" /MIN /belownormal cmd /c "script.php 2>&1"';
    pclose(popen($cmd, 'r'));

Mach es selbst mit einer Gabel : PHP bietet auch die Möglichkeit, die Gabelung über die Funktion pcntl_fork () zu verwenden . Ein gutes Tutorial dazu finden Sie hier, aber ich empfehle dringend, es nicht zu verwenden, da Gabel ein Verbrechen gegen die Menschlichkeit und insbesondere gegen oop ist.

Multithreading

Beim Multithreading teilen alle Ihre Threads ihre Ressourcen, sodass Sie ohne großen Aufwand problemlos zwischen ihnen kommunizieren und sie synchronisieren können. Auf der anderen Seite muss man wissen, was man tut, da Rennbedingungen und Deadlocks einfach zu produzieren, aber sehr schwer zu debuggen sind.

Standard-PHP bietet kein Multithreading, aber es gibt eine (experimentelle) Erweiterung, die dies tatsächlich tut - Pthreads . Seine API-Dokumentation hat es sogar in php.net geschafft . Damit können Sie einige Dinge wie in echten Programmiersprachen tun :-) wie folgt:

class MyThread extends Thread {
    public function run(){
        //do something time consuming
    }
}

$t = new MyThread();
if($t->start()){
    while($t->isRunning()){
        echo ".";
        usleep(100);
    }
    $t->join();
}

Für Linux gibt es hier bei stackoverflow's eine Installationsanleitung .

Für Windows gibt es jetzt eines:

  • Zuerst benötigen Sie die thread-sichere Version von PHP.
  • Sie benötigen die vorkompilierten Versionen beider pthreads und deren PHP-Erweiterung. Sie können hier heruntergeladen werden . Stellen Sie sicher, dass Sie die Version herunterladen, die mit Ihrer PHP-Version kompatibel ist.
  • Kopieren Sie php_pthreads.dll (von der soeben heruntergeladenen Zip-Datei) in Ihren PHP-Erweiterungsordner ([phpDirectory] / ext).
  • Kopieren Sie pthreadVC2.dll in [phpDirectory] (den Stammordner - nicht den Erweiterungsordner).
  • Bearbeiten Sie [phpDirectory] /php.ini und fügen Sie die folgende Zeile ein

    extension=php_pthreads.dll
  • Testen Sie es mit dem obigen Skript mit etwas Schlaf oder etwas genau dort, wo der Kommentar ist.

Und jetzt das große ABER : Obwohl dies wirklich funktioniert, war PHP ursprünglich nicht für Multithreading gemacht. Es gibt eine thread-sichere Version von PHP und ab Version 5.4 scheint es nahezu fehlerfrei zu sein, aber die Verwendung von PHP in einer Multithread-Umgebung wird im PHP-Handbuch immer noch nicht empfohlen (aber möglicherweise haben sie ihr Handbuch einfach nicht aktualisiert dies noch). Ein viel größeres Problem könnte sein, dass viele gängige Erweiterungen nicht threadsicher sind . Möglicherweise erhalten Sie Threads mit dieser PHP-Erweiterung, aber die Funktionen, von denen Sie abhängig sind, sind immer noch nicht threadsicher, sodass Sie wahrscheinlich auf Rennbedingungen, Deadlocks usw. in Code stoßen, den Sie nicht selbst geschrieben haben ...

Francois Bourgeois
quelle
5
Das ist schrecklich falsch. Der Artikel, auf den Sie verwiesen haben, stammt aus dem Jahr 2008. Wenn PHP im Kern nicht threadsicher wäre, hätte es keine SAPI-Module mit Threading erstellt.
Joe Watkins
1
@ Joe: Okay, ich habe es im Core geändert ist threadsicher, aber viele Erweiterungen sind es nicht.
Francois Bourgeois
1
Viele ? Ich denke, Sie werden feststellen, dass es nur sehr wenige sind. Sie haben die Dokumentation gefunden, aber nicht richtig gelesen: Hinweis: Die mit * gekennzeichneten sind keine thread-sicheren Bibliotheken und sollten nicht mit PHP als Servermodul im Multi verwendet werden -Threaded Windows-Webserver (IIS, Netscape). Dies spielt in Unix-Umgebungen noch keine Rolle.
Joe Watkins
6
PHP ist sehr threadsicher und seit vielen Jahren sind einige der externen Bibliotheken und einige gebündelte Bibliotheken nicht mehr vorhanden, aber es ist gut dokumentiert und trotzdem ziemlich offensichtlich. pthreads erstellt Threads, die genauso sicher sind wie die von zend in einem Multithread-Sapi erstellten Threads. Ich weiß das, weil ich allein pthreads geschrieben habe. Es verwendet jede verfügbare API, die von PHP verfügbar gemacht wird, genau wie die Server-APIs. Ich sage nicht, dass es vollständig stabil ist, aber das Bild, das Sie gezeichnet haben, ist einfach falsch und sehr schlecht informiert.
Joe Watkins
@Joe: Wenn das Handbuch besagt, dass dies für Unix-Umgebungen keine Rolle spielt, beziehen sie sich auf die Tatsache, dass Apache unter Unix-Systemen mehrere Prozesse und unter Windows Threads verwendet. Im Grunde sagen sie also: "Wenn Sie ohnehin keine Threads verwenden, müssen Sie sich keine Gedanken über nicht threadsichere Erweiterungen machen." Wenn wir Threads mit Pthreads verwenden, spielt dies natürlich auch in Unix-Umgebungen eine Rolle.
Francois Bourgeois
17

Sie können pcntl_fork () verwenden , um etwas Ähnliches wie Threads zu erreichen. Technisch gesehen handelt es sich um separate Prozesse, sodass die Kommunikation zwischen beiden mit Threads nicht so einfach ist, und ich glaube, dass es nicht funktionieren wird, wenn PHP von Apache aufgerufen wird.

davr
quelle
4
Ich verwende pcntl_fork erfolgreich, um eine ziemlich umfangreiche Datenimportaufgabe zu parallelisieren. Funktioniert super und ich hatte es in ungefähr einer Stunde geschafft. Es gibt eine gewisse Lernkurve, aber sobald Sie verstanden haben, was los ist, ist es ziemlich einfach.
Frank Farmer
Frank, ist das mit CLI PHP oder Apache PHP?
Artem Russakovskii
@Artem: Ich würde es auch gerne wissen.
Josh K
5
@ Frank Farmer neckt uns ... genau wie das PECL-Paket.
Roger
1
Ich habe pcntl_fork mit CLI verwendet. Ich habe es nie in Apache versucht; das klingt riskant. Selbst bei CLI gab es einige unerwartete Probleme. Ich schien ein Problem zu haben, bei dem ein Kind, wenn es ein Datenbankhandle schloss (weil es seine Arbeit beendet hatte), auch die Verbindung für Geschwister schloss. Da Kinder Kopien der Eltern sind, bereiten Sie sich auf die Seltsamkeit vor. Seitdem habe ich meinen Code neu gestaltet, um einfach neue, vollständig getrennte Prozesse über exec () zu erzeugen - auf diese Weise ist es sauberer.
Frank Farmer
7

pcntl_fork()ist das, wonach Sie suchen, aber sein Prozess gibt kein Threading. Sie haben also das Problem des Datenaustauschs. Um sie zu lösen, können Sie PHPS-Semaphorfunktionen ( http://www.php.net/manual/de/ref.sem.php ) verwenden. Nachrichtenwarteschlangen sind am Anfang möglicherweise etwas einfacher als Segmente mit gemeinsamem Speicher.

Wie auch immer, eine Strategie, die ich in einem von mir entwickelten Webframework verwende, das ressourcenintensive Blöcke einer Webseite (wahrscheinlich mit externen Anforderungen) parallel lädt: Ich mache eine Jobwarteschlange, um zu wissen, auf welche Daten ich warte, und dann verzweige ich mich aus den Jobs für jeden Prozess. Sobald dies erledigt ist, speichern sie ihre Daten im APC-Cache unter einem eindeutigen Schlüssel, auf den der übergeordnete Prozess zugreifen kann. Sobald alle Daten vorhanden sind, werden sie fortgesetzt. Ich benutze einfach usleep()zu warten, weil prozessübergreifende Kommunikation in Apache nicht möglich ist (Kinder verlieren die Verbindung zu ihren Eltern und werden Zombies ...). Das bringt mich zum letzten Punkt: Es ist wichtig, jedes Kind selbst zu töten! Es gibt auch Klassen, die Prozesse verzweigen, aber Daten behalten. Ich habe sie nicht untersucht, aber das Zend-Framework hat eine, und sie codieren normalerweise langsam, aber zuverlässig. Sie finden es hier: http://zendframework.com/manual/1.9/en/zendx.console.process.unix.overview.html Ich denke, sie verwenden shm-Segmente! Nun, last but not least gibt es einen Fehler auf dieser Zend-Website, ein kleiner Fehler im Beispiel.

while ($process1->isRunning() && $process2->isRunning()) {
    sleep(1);
}
should of course be:
while ($process1->isRunning() || $process2->isRunning()) {
    sleep(1);
}
Der Surrican
quelle
6

Es gibt eine Threading Erweiterung activley auf PThreads basierend entwickelt , dass sieht sehr vielversprechend an https://github.com/krakjoe/pthreads

JasonDavis
quelle
5

Ich habe eine PHP-Threading-Klasse, die seit über zwei Jahren in einer Produktionsumgebung einwandfrei läuft.

BEARBEITEN: Dies ist jetzt als Komponistenbibliothek und als Teil meines MVC-Frameworks Hazaar MVC verfügbar.

Siehe: https://git.hazaarlabs.com/hazaar/hazaar-thread

Jamie Carl
quelle
Was ist, wenn das Programm in file.php nach Ihrem Beispiel beispielsweise die Existenz einer Liste der Uris von 10k-Websites bestätigt und dann das Ergebnis in einer CSV-Datei speichern muss? Problem?
Roger
Der Unterprozess wird als derselbe Benutzer wie das Webserver / übergeordnete Skript ausgeführt. Wenn Sie also Dateien schreiben, haben Sie hinsichtlich der Berechtigungen die gleichen Überlegungen wie normalerweise. Wenn Sie Probleme beim Schreiben von Dateien haben, versuchen Sie, in / tmp zu schreiben. Wenn dies funktioniert, gehen Sie von dort aus.
Jamie Carl
1
Der Link ist jetzt aufgrund einer Neugestaltung tot. Sie können ihn hier auf dem Wayback-Computer herunterladen
Tony
Jetzt zu meinem MVC-Framework hinzugefügt. Siehe: git.hazaarlabs.com/hazaar/hazaar-thread
Jamie Carl
2

Ich weiß, dass dies eine sehr alte Frage ist, aber Sie können sich http://phpthreadlib.sourceforge.net/ ansehen.

Bidirektionale Kommunikation, Unterstützung für Win32 und keine Erweiterungen erforderlich.

Ohne Vorzeichen
quelle
1

Schon mal was davon gehört appserver von techdivision gehört?

Es ist in PHP geschrieben und arbeitet als App-Server, der Multithreads für PHP-Anwendungen mit hohem Datenverkehr verwaltet. Ist noch in der Beta aber sehr vielversprechend.

user2627170
quelle
-3

Es gibt die eher obskure und bald veraltete Funktion namens Zecken . Das einzige, wofür ich es jemals verwendet habe, ist, einem Skript zu erlauben, SIGKILL (Strg + C) zu erfassen und ordnungsgemäß zu schließen.

troelskn
quelle
3
Ticks werden nicht parallel ausgeführt. Im Wesentlichen wird nach jeder Anweisung Ihre Tick-Funktion ausgeführt. Während Ihre Tick-Funktion ausgeführt wird, wird der Hauptcode nicht ausgeführt.
Frank Farmer
1
Ticks werden nur für den signal () - Handler benötigt.
Nick