Dieser Artikel stellt hauptsächlich die Implementierung von Multiprozessen und Multithreading in PHP vor. Er hat einen gewissen Referenzwert. Jetzt kann ich ihn mit allen teilen, die ihn brauchen.
Anleitung für Neulinge.
Verwaister Prozess: Ein übergeordneter Prozess wird beendet, während einer oder mehrere seiner untergeordneten Prozesse noch ausgeführt werden. Diese untergeordneten Prozesse werden dann zu verwaisten Prozessen. Der verwaiste Prozess wird vom Init-Prozess übernommen (Prozessnummer ist 1) und der Init-Prozess schließt die Statuserfassungsarbeit für ihn ab.
Zombie-Prozess: Ein Prozess verwendet fork, um einen untergeordneten Prozess zu erstellen, wenn der untergeordnete Prozess beendet wird und der übergeordnete Prozess nicht „wait“ oder „waitpid“ aufruft, um den Status zu erhalten Informationen des untergeordneten Prozesses. Dann wird der Prozessdeskriptor des untergeordneten Prozesses weiterhin im System gespeichert. Dieser Prozess wird als Zombie-Prozess bezeichnet.
Gefahren des Zombie-Prozesses: Wenn der Prozess nicht wait/waitpid aufruft, Dann werden die gespeicherten Informationen nicht freigegeben und ihre Prozessnummer wird immer belegt. Die Prozessnummer, die vom System verwendet werden kann, ist jedoch begrenzt durch den Mangel an verfügbaren Prozessnummern kann das System keine neuen Prozesse generieren. Dies ist der Schaden von Zombie-Prozessen und sollte vermieden werden. Jeder untergeordnete Prozess (außer init) verschwindet nicht sofort nach exit(), sondern hinterlässt eine Datenstruktur, die als Zombie-Prozess (Zombie) bezeichnet wird und auf die Verarbeitung durch den übergeordneten Prozess wartet.
Die Lösung für den generierten Zombie-Prozess: Töten Sie den übergeordneten Prozess und den Zombie-Prozess Es wird generiert. Werden zu verwaisten Prozessen, diese verwaisten Prozesse werden vom Init-Prozess übernommen, und der Init-Prozess wartet () auf diese verwaisten Prozesse und gibt die von ihnen belegten Ressourcen in der Systemprozesstabelle frei.
Lösung für den Zombie-Prozess
(1) Durch den Signalmechanismus
Wenn das Kind Der Prozess wird beendet. Senden Sie das SIGCHILD-Signal an den übergeordneten Prozess. Der übergeordnete Prozess verarbeitet das SIGCHILD-Signal. Rufen Sie „wait“ in der Signalverarbeitungsfunktion auf, um den Zombie-Prozess zu verarbeiten.
(2) zweimal verzweigen
Abschnitt 8.6 von „Erweiterte Programmierung in Unix-Umgebungen“ ist sehr detailliert. Das Prinzip besteht darin, den untergeordneten Prozess in einen verwaisten Prozess umzuwandeln, sodass sein übergeordneter Prozess zu einem Init-Prozess wird und der Zombie-Prozess über den Init-Prozess verarbeitet werden kann.
Vergleich zwischen Multiprozess und Multithread
Kontrastabmessungen |
Multiprozess |
Multi- Thread |
Zusammenfassung |
Datenaustausch, Synchronisierung |
Der Datenaustausch ist komplex und erfordert IPC; die Daten werden getrennt und die Synchronisierung ist einfach |
Da Prozessdaten gemeinsam genutzt werden, ist die Datenfreigabe einfach, aber aus diesem Grund ist auch die Synchronisierung kompliziert |
Jedes hat seine eigenen Vorteile |
Speicher, CPU |
Beanspruchen viel Speicher, komplexes Umschalten, geringe CPU-Auslastung | Beansprucht wenig Speicher, einfaches Umschalten, hohe CPU-Auslastung |
Thread-Dominanz |
Erstellen , zerstören, wechseln |
Erstellung, Zerstörung und Wechsel sind komplex und langsam |
Erstellung, Zerstörung und Wechsel sind einfach und schnell |
Threadbelegung ausgezeichnet |
Programmierung und Debugging |
Einfache Programmierung und einfaches Debuggen |
Komplexe Programmierung, kompliziertes Debuggen |
Prozessdominanz |
Zuverlässigkeit |
Prozesse beeinflussen sich nicht gegenseitig |
Wenn ein Thread hängen bleibt, bleibt der gesamte Prozess hängen |
Der Prozess nutzt die Vorteile |
Verteilt |
Geeignet für die Multi-Core- und Multi-Machine-Verteilung; Eine Maschine reicht nicht aus, es ist einfacher, auf mehrere Maschinen zu erweitern |
An die Multi-Core-Verteilung angepasst |
Prozessdominanz
|
1) Priorisierte Threads, die häufig erstellt und gelöscht werden müssen
Den Grund finden Sie im Vergleich oben.
Die häufigste Anwendung dieses Prinzips ist der Webserver. Eine Verbindung erstellt einen Thread, und wenn er getrennt wird, wird der Thread zerstört. Wenn ein Prozess verwendet wird, sind die Kosten für die Erstellung und Zerstörung unerträglich 🎜>
2) Priorisieren Sie die Verwendung von Threads, die eine große Menge an Berechnungen erfordern
Die sogenannte große Menge an Berechnungen verbraucht natürlich viel CPU und Schalter In diesem Fall sind Threads am besten geeignet. Die gebräuchlichsten Prinzipien dieser Art sind Bildverarbeitung und Algorithmenverarbeitung.3) Threads werden für die Verarbeitung starker Korrelationen verwendet, und Prozesse werden für die Verarbeitung schwacher Korrelationen verwendet
Was sind starke Korrelation und schwache Korrelation? Es ist schwierig, es theoretisch zu definieren, aber Sie können es anhand eines einfachen Beispiels verstehen. Ein allgemeiner Server muss die folgenden Aufgaben ausführen: Senden und Empfangen von Nachrichten, Nachrichtenverarbeitung. „Nachrichtensenden und -empfangen“ und „Nachrichtenverarbeitung“ sind schwach verwandte Aufgaben, und „Nachrichtenverarbeitung“ kann in „Nachrichtendekodierung“ und „Geschäftsverarbeitung“ unterteilt werden. Diese beiden Aufgaben sind relativ viel enger miteinander verbunden. Daher können „Nachrichtensenden und -empfangen“ und „Nachrichtenverarbeitung“ in separaten Prozessen entworfen werden, und „Nachrichtendekodierung“ und „Geschäftsverarbeitung“ können in separaten Threads entworfen werden. Natürlich ist diese Aufteilungsmethode nicht statisch und kann auch entsprechend der tatsächlichen Situation angepasst werden.4) Es kann auf verteilte Benutzerprozesse mit mehreren Maschinen und verteilte Benutzerthreads mit mehreren Kernen erweitert werden.
Bitte sehen Sie sich den Vergleich oben für den Grund an.5) Wenn alle Anforderungen erfüllt sind, verwenden Sie die Methode, mit der Sie am besten vertraut sind und die Sie am besten können.
Was „Datenfreigabe, Synchronisierung“, „Programmierung, Debugging“ betrifft „Wie man zwischen der sogenannten „Komplexität und Einfachheit“ in den Dimensionen „Zuverlässigkeit“ wählen kann, kann ich nur sagen: Es gibt keine klare Auswahlmethode. Aber ich kann Ihnen ein Auswahlprinzip nennen: Wenn sowohl Multi-Processing als auch Multi-Threading die Anforderungen erfüllen können, dann wählen Sie das, mit dem Sie am besten vertraut sind und das Sie am besten können. Was daran erinnert werden muss: Obwohl ich so viele Auswahlprinzipien angegeben habe, sind tatsächliche Anwendungen im Grunde eine Kombination aus „Prozess + Thread“.Ressourcenverbrauch:
Aus Sicht des Kernels besteht der Zweck des Prozesses darin, als Grundlage für die Zuweisung von Systemressourcen zu dienen (CPU-Zeit, Speicher usw.) Einheit. Ein Thread ist ein Ausführungsstrom eines Prozesses und die Grundeinheit der CPU-Planung und -Verteilung. Es handelt sich um eine Grundeinheit, die kleiner als ein Prozess ist und unabhängig ausgeführt werden kann.Threads nutzen untereinander denselben Adressraum und teilen sich die meisten Daten. Der zum Starten eines Threads benötigte Speicherplatz ist viel kürzer als der zum Starten eines Prozesses . Viel weniger Zeit als der Zeitaufwand für den Wechsel zwischen Prozessen. Laut Statistik beträgt der Overhead eines Prozesses im Allgemeinen etwa das 30-fache des Overheads eines Threads. Auf bestimmten Systemen können diese Daten natürlich erheblich unterschiedlich sein.
Kommunikationsmethode:
Die einzige Möglichkeit, Daten zwischen Prozessen zu übertragen, ist die Kommunikation, was zeitaufwändig und unbequem ist. Die meisten Thread-Zeitdaten werden gemeinsam genutzt (nicht innerhalb der Thread-Funktion), was schnell und bequem ist. Für die Datensynchronisierung sind jedoch Sperren erforderlich, und statischen Variablen sollte besondere Aufmerksamkeit gewidmet werden.
Thread-eigene Vorteile:
Verbesserung der Anwendungsreaktion, wodurch Systeme mit mehreren CPUs effizienter werden. Das Betriebssystem stellt sicher, dass unterschiedliche Threads auf unterschiedlichen CPUs ausgeführt werden, wenn die Anzahl der Threads nicht größer ist als die Anzahl der CPUs.
Verbesserung der Programmstruktur. Ein langer und komplexer Prozess kann in mehrere Threads unterteilt werden und in mehrere unabhängige oder halbunabhängige laufende Teile umgewandelt werden. Ein solches Programm ist leichter zu verstehen und zu ändern.
/** * 入口函数 * 将此文件保存为 ProcessOpera.php * 在terminal中运行 /usr/local/php/bin/php ProcessOpera.php & * 查看进程 ps aux|grep php */ ProcessOpera("runCode", array(), 8); /** * run Code */ function runCode($opt = array()) { //需要在守护进程中运行的代码 } /** * $func为子进程执行具体事物的函数名称 * $opt为$func的参数 数组形式 * $pNum 为fork的子进程数量 */ function ProcessOpera($func, $opts = array(), $pNum = 1) { while(true) { $pid = pcntl_fork(); if($pid == -1) { exit("pid fork error"); } if($pid) { static $execute = 0; $execute++; if($execute >= $pNum) { pcntl_wait($status); $execute--; } } else { while(true) { //somecode $func($opts); sleep(1); } exit(0); } } }
class My extends Thread { protected $name; public $runing; function __construct($name){ $this->runing=1; $this->param=0; $this->name=$name; } public function run() { while($this->runing){ if($this->param){ $time=rand(1,5); echo 'I am thread '.$this->name.',pid: '.$this->getCreatorId().",param: {$this->param},need {$time}s\n"; sleep($time); $this->param=0; }else{ echo "Thread {$this->name} waiting...\n"; } sleep(1); } } } $pool=array(); $pool[]=new My('a'); $pool[]=new My('b'); $pool[]=new My('c'); //开启所有线程 foreach ($pool as $w) { $w->start(); } //派发任务 unset($w); for($i=1;$i<10;$i++){ $woker_content=$i; while(1){ foreach($pool as $w){ if(!$w->param){ $w->param=$woker_content; echo "Thread {$w->name} empty,put param {$woker_content}.\n"; break 2; } } sleep(1); } } unset($w); while(count($pool)){ foreach ($pool as $k => $w) { if(!$w->param){ $w->runing=false; unset($pool[$k]); echo "Thread {$w->name} end,exit!\n"; } } sleep(1); } echo 'All thread end!';
Verwandte Empfehlungen:
Detaillierte Erläuterung von fünf Möglichkeiten zur Implementierung geplanter Aufgaben in PHP
Das obige ist der detaillierte Inhalt vonPHP implementiert Multiprozess und Multithreading. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!