Cet article vous apporte une explication détaillée des coroutines PHP (avec des exemples). Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. J'espère qu'il vous sera utile.
Avant de parler de coroutines, parlons de multi-processus, multi-threads, de parallélisme et de concurrence.
Pour les processeurs monocœur, le principe du multitâche multi-processus est de laisser le système d'exploitation allouer une certaine tranche de temps CPU à une tâche à chaque fois, puis de l'interrompre, de laisser la tâche suivante exécuter une certaine tranche de temps, puis interrompre à nouveau et passer au suivant, et ainsi de suite.
Le changement de tâche d'exécution étant très rapide, cela donne aux utilisateurs externes l'impression que plusieurs tâches sont exécutées en même temps.
La planification multi-processus est implémentée par le système d'exploitation. Le processus lui-même ne peut pas contrôler le moment où il est planifié. En d'autres termes : 进程的调度
est implémenté par la couche externe 调度器抢占式
Le. La coroutine nécessite que la tâche en cours d'exécution redonne automatiquement le contrôle au planificateur afin que les autres tâches puissent continuer à s'exécuter. C'est exactement le contraire du multitâche de 抢占式
. Le planificateur qui anticipe le multitâche peut interrompre de force les tâches en cours, quelles que soient ses propres intentions. Si seulement le programme cédait automatiquement le contrôle, il serait facile pour un programme malveillant d'occuper tout le temps CPU sans le partager avec d'autres tâches.
La planification de la coroutine est implémentée par la coroutine elle-même 主动
cédant le contrôle au planificateur externe
Pour revenir à l'exemple du générateur implémentant la fonction xrange, l'ensemble du processus d'exécution L'alternance peut être représentée par la figure suivante :
la coroutine peut être comprise comme 纯用户态的线程
, et le changement de tâche est effectué via 协作
au lieu de préemption.
Par rapport aux processus ou aux threads, toutes les opérations des coroutines peuvent être effectuées en mode utilisateur au lieu du mode noyau du système d'exploitation, et le coût de création et de commutation est très faible.
Pour faire simple 协程
consiste à fournir une méthode pour interrompre l'exécution de la tâche en cours, enregistrer les variables locales actuelles et restaurer les variables locales actuelles pour continuer l'exécution la prochaine fois.
Nous pouvons diviser la grande tâche en plusieurs petites tâches et les exécuter à tour de rôle. S'il y a une petite tâche en attente d'E/S système, ignorez-la et exécutez la petite tâche suivante. et-vient pour réaliser les IO. L'exécution parallèle des opérations et des calculs CPU améliore généralement l'efficacité d'exécution des tâches, ce qui est le sens des coroutines
Multi-threads
Sous un seul cœur, les multi-threads doivent être concurrent;
Cependant, le multithreading actuel des processus unifiés peut s'exécuter sur des processeurs multicœurs, il peut donc être parallélisé
fait référence à la capacité de gérer plusieurs activités simultanées , les événements simultanés ne doivent pas nécessairement se produire au même moment.
fait référence à deux événements simultanés qui se produisent en même temps, ce qui signifie concurrence, mais la concurrence n'est pas nécessairement parallèle.
Plusieurs opérations peuvent être effectuées sur des périodes qui se chevauchent.
并发
fait référence à la structure du programme, 并行
fait référence à l'état du programme lorsqu'il est en cours d'exécution 并行
doit être simultané, 并行
C'est un type de 并发
conception
Un seul thread ne peut jamais atteindre l'état 并行
Le support de Coroutine est ajouté en fonction de 生成器
Une fonction qui peut renvoyer des données au générateur (l'appelant envoie des données à la fonction générateur appelée
Cela transforme la communication unidirectionnelle du générateur vers l'appelant en une communication bidirectionnelle entre les deux Nous avons déjà parlé de la méthode d'envoi dans le dernier article. Comprenons la coroutine
function printNum($max, $caller) { for ($i=0; $i<$max; $i++ ) { echo "调度者:" . $caller . " 打印:" . $i . PHP_EOL; } } printNum(3, "caller1"); printNum(3, "caller2"); # output 调度者:caller1 打印:0 调度者:caller1 打印:1 调度者:caller1 打印:2 调度者:caller2 打印:0 调度者:caller2 打印:1 调度者:caller2 打印:2
# 本代码手动调整了进程执行代码的顺序,当然本代码实现不用协程也可以,只是利用本流程说明协程作用 # 生成器给了我们函数中断,协程[生成器send]给了我们重新唤起生成器函数的能力 function printNumWithGen($max) { for ($i=0; $i<$max; $i++ ) { $res = yield $i; echo $res; } } $gen1 = printNumWithGen(3); $gen2 = printNumWithGen(3); // 手动执行caller1 再 caller2 $gen1->send("调度者: caller1 打印:" . $gen1->current() . PHP_EOL); $gen2->send("调度者: caller2 打印:" . $gen2->current() . PHP_EOL); // 手动执行caller1 再 caller2 $gen1->send("调度者: caller1 打印:" . $gen1->current() . PHP_EOL); $gen2->send("调度者: caller2 打印:" . $gen2->current() . PHP_EOL); // 手动执行caller2 再 caller1 $gen2->send("调度者: caller2 打印:" . $gen2->current() . PHP_EOL); $gen1->send("调度者: caller1 打印:" . $gen1->current() . PHP_EOL); # output 调度者: caller1 打印:0 调度者: caller2 打印:0 调度者: caller1 打印:1 调度者: caller2 打印:1 调度者: caller2 打印:2 调度者: caller1 打印:2
, nous créerons alors automatiquement un planificateur automatique (Co exécuteur automatique) pour nos coroutines, il n'est donc pas nécessaire d'interrompre et de reprendre manuellement
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!