Cet article présente principalement l'implémentation du multi-processus et du multi-threading en PHP. Il a une certaine valeur de référence. Maintenant, je le partage avec tout le monde. Les amis dans le besoin peuvent s'y référer
Instructions pour les débutants :
Processus orphelin : un processus parent se termine alors qu'un ou plusieurs de ses processus enfants sont toujours en cours d'exécution, ces processus enfants deviendront alors des processus orphelins. Le processus orphelin sera adopté par le processus d'initialisation (le numéro de processus est 1) et le processus d'initialisation terminera le travail de collecte de statut pour eux.
Processus zombie : un processus utilise fork pour créer un processus enfant si le processus enfant se termine et que le processus parent n'appelle pas wait ou waitpid pour obtenir le statut. Informations sur le processus enfant, Ensuite, le descripteur de processus du processus enfant est toujours enregistré dans le système. Ce processus est appelé processus zombie.
Dangers du processus zombie : Si le processus n'appelle pas wait/waitpid, Ensuite, les informations conservées ne seront pas divulguées et leur numéro de processus sera toujours occupé. Cependant, le numéro de processus pouvant être utilisé par le système est limité si un grand nombre de processus zombies sont générés. par le manque de numéros de processus disponibles. Le système ne peut pas générer de nouveaux processus. Il s'agit du risque de processus zombies et doit être évité. Tout processus enfant (sauf init) ne disparaît pas immédiatement après exit(), mais laisse une structure de données appelée processus zombie (Zombie), en attente du processus parent.
La solution au processus zombie qui a été généré : Tuez le processus parent et le processus zombie il génère des processus Devenir orphelins, ces processus orphelins seront repris par le processus d'initialisation, et le processus d'initialisation attendra() ces processus orphelins et libérera les ressources dans la table des processus système qu'ils occupent.
Solution au processus zombie
(1) Grâce au mécanisme de signal
Lorsque l'enfant le processus se termine Envoyez le signal SIGCHILD au processus parent, et le processus parent gère le signal SIGCHILD. Appelez l'attente dans la fonction de traitement du signal pour gérer le processus zombie.
(2) fork deux fois
La section 8.6 de « Programmation avancée dans un environnement Unix » est très détaillée. Le principe est de transformer le processus enfant en processus orphelin, de sorte que son processus parent devienne un processus d'initialisation et que le processus zombie puisse être traité via le processus d'initialisation.
Comparaison entre multi-processus et multi-thread
Dimensions de contraste |
Multi-processus |
Multi- fil de discussion |
Résumé |
Partage de données, synchronisation |
Le partage de données est complexe et nécessite que les données IPC soient séparées et la synchronisation est simple |
Parce que les données de processus sont partagées, le partage des données est simple, mais c'est aussi pour cette raison que la synchronisation est compliquée |
Chacun a ses propres avantages |
Mémoire, CPU |
Occupe beaucoup de mémoire, commutation complexe, faible utilisation du processeur | Prendre peu de mémoire, commutation simple, utilisation élevée du processeur |
Dominance des threads |
Créer , détruire, changer |
La création, la destruction et la commutation sont complexes et lentes |
La création, la destruction et la commutation sont simples et rapides |
Occupation des threads Excellent |
Programmation et débogage |
Programmation et débogage faciles |
Programmation complexe, débogage compliqué |
Domination des processus |
Fiabilité |
Les processus ne s'affecteront pas les uns les autres |
Si un thread raccroche, l'ensemble du processus raccrochera |
Le processus en profite |
Distribué |
Convient à la distribution multi-cœurs et multi-machines si ; une machine ne suffit pas, il est plus facile de s'étendre à plusieurs machines |
Adapté à la distribution multicœur |
Dominance des processus
|
1) Fils de discussion prioritaires qui doivent être fréquemment créés et détruits
Veuillez consulter la comparaison ci-dessus pour la raison.
L'application la plus courante de ce principe est le serveur web. Une connexion crée un thread, et lorsqu'elle est déconnectée, le thread est détruit si un processus est utilisé, le coût de création et de destruction est insupportable. 🎜>
2) Prioriser l'utilisation de threads qui nécessitent une grande quantité de calculs
La soi-disant grande quantité de calculs, bien sûr, consomme beaucoup de CPU et de commutateurs fréquemment. Dans ce cas, les threads sont les plus adaptés. Les principes les plus courants de ce type sont le traitement d'images et le traitement d'algorithmes.3) Les threads sont utilisés pour le traitement de corrélation forte, et les processus sont utilisés pour le traitement de corrélation faible
Qu'est-ce qu'une corrélation forte et une corrélation faible ? C’est difficile à définir en théorie, mais vous pouvez le comprendre avec un exemple simple. Un serveur général doit effectuer les tâches suivantes : envoi et réception de messages, traitement des messages. « L'envoi et la réception de messages » et le « traitement des messages » sont des tâches faiblement liées, et le « traitement des messages » peut être divisé en « décodage des messages » et « traitement métier ». Ces deux tâches sont relativement beaucoup plus étroitement liées. Par conséquent, « l'envoi et la réception de messages » et le « traitement des messages » peuvent être conçus dans des processus distincts, et le « décodage des messages » et le « traitement métier » peuvent être conçus dans des threads distincts. Bien entendu, cette méthode de division n'est pas statique et peut également être ajustée en fonction de la situation réelle.4) Il peut être étendu aux processus utilisateur distribués multi-machines et aux threads utilisateur distribués multicœurs
Veuillez consulter la comparaison ci-dessus pour la raison.5) Lorsque toutes les conditions sont remplies, utilisez la méthode qui vous est la plus familière et la meilleure dans
Quant à "partage de données, synchronisation", "programmation, débogage ", Comment choisir entre ce qu'on appelle "la complexité et la simplicité" dans les dimensions de la "fiabilité", je peux seulement dire : il n'y a pas de méthode de choix claire. Mais je peux vous expliquer un principe de sélection : si le multitraitement et le multithreading peuvent répondre aux exigences, alors choisissez celui que vous connaissez le mieux et dans lequel vous êtes le meilleur. Ce qu'il faut rappeler est : bien que j'aie donné de nombreux principes de sélection, les candidatures réelles sont fondamentalement une combinaison de "processus + fil". Ne tombez pas vraiment dans une situation de choix.Consommation des ressources :
Du point de vue du noyau, le but du processus est de servir de base à l'allocation des ressources système (temps CPU, mémoire, etc.). Un thread est un flux d'exécution d'un processus et l'unité de base de planification et de répartition du processeur. C'est une unité de base qui est plus petite qu'un processus et peut s'exécuter indépendamment.Threads, ils utilisent le même espace d'adressage entre eux et partagent la plupart des données. L'espace nécessaire au démarrage d'un thread est bien inférieur à celui du démarrage d'un processus. De plus, le temps nécessaire pour basculer entre les threads est également loin. . Bien moins que le temps nécessaire pour basculer entre les processus. Selon les statistiques, en général, la surcharge d'un processus est environ 30 fois supérieure à celle d'un thread. Bien entendu, sur des systèmes spécifiques, ces données peuvent être considérablement différentes.
Méthode de communication :
La seule façon de transférer des données entre les processus est la communication, ce qui prend du temps et n'est pas pratique. La plupart des données de temps de thread sont partagées (non partagées dans la fonction thread), ce qui est rapide et pratique. Cependant, la synchronisation des données nécessite des verrous et une attention particulière doit être accordée aux variables statiques.
Avantages propres à Thread :
Amélioration de la réponse des applications, rendant les systèmes multi-CPU plus efficaces ; Le système d'exploitation veillera à ce que lorsque le nombre de threads n'est pas supérieur au nombre de processeurs, différents threads s'exécutent sur différents processeurs
Améliorer la structure du programme ; Un processus long et complexe peut être divisé en plusieurs threads et devenir plusieurs parties indépendantes ou semi-indépendantes. Un tel programme sera plus facile à comprendre et à modifier.
/** * 入口函数 * 将此文件保存为 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!';
Recommandations associées :
Explication détaillée de cinq façons d'implémenter des tâches planifiées en PHP
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!