Dans le domaine de PHP, la notion de multi-threading n'est pas aussi connue que dans d'autres langages. Je pensais que PHP est généralement un modèle monothread et ne convient pas aux champs multithread. Après avoir parcouru le code source de certains projets multi-thread, j'ai découvert que le multi-threading de PHP avait également de grandes utilités. Lorsqu'il est utilisé de manière flexible, il s'avère très approprié pour résoudre certains problèmes.
Multi-threading
Threads
Parlons d'abord des threads :
Le thread est la plus petite unité que le système d'exploitation peut planifier des opérations. Il est inclus dans le processus et constitue la véritable unité opérationnelle du processus. Un thread fait référence à un seul flux de contrôle séquentiel dans un processus. Plusieurs threads peuvent s'exécuter simultanément dans un processus, et chaque thread effectue différentes tâches en parallèle
L'utilisation du multithreading est principalement due au fait qu'elle présente des avantages en termes d'efficacité d'exécution. Un gros avantage. Puisqu'un thread est la plus petite unité que le système d'exploitation peut planifier :
Un programme multithread a une plus grande probabilité d'être planifié par le système d'exploitation qu'un programme monothread, donc les programmes multithread sont généralement plus efficace que les programmes monothread ;
Plusieurs threads d'un programme multithread peuvent s'exécuter sur plusieurs cœurs d'un processeur multicœur en même temps, ce qui permet de tirer pleinement parti de la machine multicœur ;
Par rapport aux programmes multi-processus en même temps, le multi-threading présente les caractéristiques suivantes :
La surcharge du système liée à la création et au changement de threads est inférieure à celle des processus, elle est donc plus efficace que plusieurs processus dans une certaine mesure ;
Les threads partagent intrinsèquement l'espace mémoire et la communication entre les threads est plus simple. Évite l'introduction d'une nouvelle complexité par le processus IPC.
Scénarios applicables
Il existe de nombreuses optimisations pour le multi-threading, mais une utilisation insensée du multi-threading ne peut pas améliorer l'efficacité d'exécution du programme, car la création et la destruction de threads, le changement de contexte, la synchronisation des threads, etc. a également une perte de performances qui peut prendre plus de temps que l'exécution séquentielle du code. Par exemple :
sumSmall est une fonction qui cumule de 1 à 50000.
L'image ci-dessus est une comparaison du moment où sumSmall est exécuté trois fois dans le thread principal et sumSmall est exécuté dans trois threads respectivement, puis les résultats sont synchronisés avec un thread. Nous constaterons que seul le temps d'exécution du thread principal est en fait plus court. Le temps de création, de commutation et de synchronisation des trois threads est bien supérieur au temps économisé par l'exécution asynchrone des threads.
La fonction sumLarge cumule de 1 à 5 000 000. La figure suivante montre le temps nécessaire pour exécuter le même thread trois fois et trois threads :
Cette fois , multi-threading Enfin, il y a un avantage en termes d'efficacité.
L'utilisation du multithread doit être déterminée en fonction des besoins spécifiques. Généralement, les deux situations suivantes sont prises en compte :
Le blocage des E/S entraînera la planification des tâches dans le système d'exploitation et le blocage. la tâche en cours, donc dans le code Lorsqu'il y a beaucoup d'E/S, le code peut être parallélisé lors de l'utilisation du multi-threading. Par exemple, lire un fichier entier plusieurs fois ou demander plusieurs ressources réseau.
Le multi-threading peut utiliser pleinement le processeur, donc lorsqu'il y a plusieurs codes gourmands en calculs, vous pouvez également utiliser le multi-threading pour les exécuter en parallèle, comme dans le dernier exemple ci-dessus.
Multi-threading en PHP
PHP ne prend pas en charge le multi-threading par défaut. Pour utiliser le multi-threading, vous devez installer l'extension pthread. Pour installer l'extension pthread, vous devez utiliser. le paramètre --enable-maintainer-zts. Recompiler PHP Ce paramètre spécifie l'utilisation de la sécurité des threads lors de la compilation de PHP.
Sécurité des threads
Le multi-threading est un facteur qui rend les programmes agités. Avant d'utiliser le multi-threading, vous devez d'abord considérer les problèmes de sécurité des threads :
Sécurité des threads : sécurité des threads. est un terme en programmation, qui signifie que lorsqu'une certaine fonction ou bibliothèque de fonctions est appelée dans un environnement multithread, elle peut gérer correctement les variables partagées entre plusieurs threads, afin que la fonction du programme puisse être complétée correctement.
En multi-threading traditionnel, puisque plusieurs threads partagent des variables, les problèmes suivants peuvent survenir :
Il existe un tableau global $arr = array('a');;
Un thread obtient la longueur du tableau est de 1 ;
Le thread B obtient la longueur du tableau est de 1 ;
Un thread fait apparaître l'élément du tableau $a = array_pop($arr $a); = 'a';;
Le fil B fait également apparaître les éléments du tableau $b = array_pop($arr); $a = null;;
À ce moment, un événement surnaturel s'est produit dans le fil B , évidemment La longueur du tableau est supérieure à 0, ou rien ne sort ;
Implémentation PHP
La sécurité des threads implémentée par PHP utilise principalement le mécanisme TSRM pour isoler les variables globales et les variables statiques, et séparer variables globales et variables statiques. Les variables sont copiées dans chaque thread, et chaque thread utilise une sauvegarde du thread principal, évitant ainsi les conflits de variables et les problèmes de sécurité des threads.
L'encapsulation multithread de PHP garantit la sécurité des threads. Les programmeurs n'ont plus besoin d'envisager d'ajouter divers verrous aux variables globales pour éviter les conflits de lecture et d'écriture. Cela réduit également le risque d'erreurs et rend le code écrit plus sécurisé.
Mais le résultat est qu'une fois que le sous-thread commence à s'exécuter, le thread principal ne peut plus ajuster les détails d'exécution du sous-thread, et le thread perd la capacité de transmettre des messages entre les threads via des variables globales pour une certaine mesure.
Dans le même temps, une fois que PHP a activé l'option de sécurité des threads, il y aura des pertes supplémentaires lors de l'utilisation du mécanisme TSRM pour allouer et utiliser des variables. Par conséquent, dans un environnement PHP qui ne nécessite pas de multi-threading, utilisez la version ZTS (non-thread safety) de PHP Très bien.
Cours et méthodes
PHP encapsule les threads dans la classe Thread. La création d'un thread est réalisée en instanciant un objet thread. En raison de l'encapsulation de la classe, l'utilisation des variables ne peut être transmise que via le constructeur, et l'opération du thread résulte. doivent également être transmis via les variables de classe sortantes.
Ce qui suit présente plusieurs méthodes de classe Thread couramment utilisées :
run():此方法是一个抽象方法,每个线程都要实现此方法,线程开始运行后,此方法中的代码会自动执行; start():在主线程内调用此方法以开始运行一个线程; join():各个线程相对于主线程都是异步执行,调用此方法会等待线程执行结束; kill():强制线程结束; isRunning():返回线程的运行状态,线程正在执行run()方法的代码时会返回 true;
En raison de l'implémentation de la sécurité des threads, une fois que les multithreads PHP ont commencé à s'exécuter, ils ne peuvent plus communiquer via la mémoire partagée. l'espace, et les threads ne peuvent pas être réutilisés via la communication inter-thread, donc je pense que le "pool de threads" de PHP n'a pas de sens. La classe Pool fournie avec l'extension est une classe qui gère l'allocation multi-thread et ne sera pas présentée ici.
Exemple de code
Ce qui suit est une classe de thread utilisée pour demander une certaine interface. Ensuite, écrivez deux exemples d'applications multithread basés sur celui-ci :
class Request extends Thread { public $url; public $response; public function __construct($url) { $this->url = $url; } public function run() { $this->response = file_get_contents($this->url); } }
Requête asynchrone
Divisez la requête synchrone en plusieurs threads pour les appels asynchrones afin d'améliorer l'efficacité d'exécution du programme.
$chG = new Request("www.google.com"); $chB = new Request("www.baidu.com"); $chG ->start(); $chB ->start(); $chG->join(); $chB->join(); $gl = $chG->response; $bd = $chB->response;
Contrôle du délai d'attente
J'ai accidentellement découvert qu'un élément de contenu sur une certaine page du site Web de l'entreprise va et vient. Je ne connais pas l'implémentation spécifique, mais cela m'a donné. l'inspiration pour utiliser le multi-threading : utiliser Thread implémente de manière asynchrone un contrôle rapide des échecs et des délais d'attente.
Lorsque nous utilisons curl pour demander une adresse, nous pouvons définir respectivement le délai d'expiration de connexion et le délai d'expiration des données de curl via les paramètres CURLOPT_CONNECTTIMEOUT / CURLOPT_TIMEOUT, mais le délai d'expiration total est difficile à contrôler. De plus, le délai d'expiration ne peut pas être défini lors de l'exécution de requêtes de base de données (blog de Niao Ge : Définition du délai d'expiration des requêtes pour MySQL).
À l'heure actuelle, nous pouvons utiliser le multi-threading pour implémenter cette fonction : après avoir exécuté la méthode start() de la classe thread, n'appelez pas la méthode join(), afin que le thread reste dans un environnement asynchrone état et ne bloque pas l’exécution du thread principal.
À l'heure actuelle, le fil principal est équivalent au vaisseau amiral, et chaque sous-fil est équivalent au croiseur. Une fois le vaisseau amiral arrivé à un certain endroit, il n'est pas nécessaire d'attendre le retour du croiseur. . Il peut simplement attendre un certain temps et partir, évitant ainsi les accidents du croiseur lorsque le vaisseau amiral est en vain et ainsi de suite.
Code :
$chG = new Request("www.google.com"); $chB = new Request("www.baidu.com"); $chG->start(); $chB->start(); $chB->join(); // 此处不对chG执行join方法 sleep(1); // sleep一个能接受的超时时间 $gl = $chG->response; $bd = $chB->response; $bd->kill(); if (!$gl) { $gl = ""; // 处理异常,或在线程类内给$gl一个默认值 }
Résumé
Le scellement du multi-thread par PHP rend très frustrant l'utilisation des threads. Bien qu'il soit sûr et conserve le style simple et facile à utiliser de PHP, il ne peut pas utiliser pleinement les capacités multithread. Cependant, chaque langue a ses propres caractéristiques et accents, il n'est donc pas nécessaire de la forcer. Si vous l'aimez, vous devez la tolérer =_=.
Recommandations associées :
Exemple d'utilisation de swoole multithread asynchrone php
Un cas d'implémentation d'une classe multi-thread 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!