129 votes

Est-ce que PHP a des threads?

J'ai trouvé ce paquet PECL appelé threads , mais il n'y a pas encore de version. Et rien ne sort sur le site PHP.

179voto

Joe Watkins Points 5048

À partir du manuel PHP pour les pthreads extension:

pthreads est une API Orientée Objet qui permet à l'utilisateur de terres multi-threading en PHP. Il inclut tous les outils dont vous avez besoin pour créer des applications multi-tâches ciblées sur le Web ou de la Console. Les applications PHP peuvent créer, lire, écrire, exécuter et de les synchroniser avec les Threads, les Travailleurs et Empilables.

Aussi incroyable que cela puisse paraître, c'est tout à fait vrai. Aujourd'hui, le PHP multi-thread pour ceux qui souhaitent l'essayer.

La première version de PHP4, 22 Mai 2000, PHP a été livré avec un "thread-safe" de l'architecture - un moyen pour elle d'exécuter plusieurs instances de il est interprète dans des threads séparés en multi-thread SAPI ( Server API ) les environnements. Au cours des 13 dernières années, la conception de cette architecture a été maintenu et avancé: Il a été dans l'utilisation de la production sur les mondes plus grands sites web depuis.

Le filetage de l'utilisateur des terres n'a jamais été une préoccupation pour le PHP de l'équipe, et il ne l'est toujours pas aujourd'hui. Vous devez comprendre que dans le monde où le PHP c'est le business, il y a déjà défini une méthode de mise à l'échelle - ajout de matériel. Depuis de nombreuses années en PHP a existé, le matériel a de moins en moins chères et c'est devenu de moins en moins une préoccupation pour le PHP de l'équipe. Alors qu'il était de moins en moins cher, il a également obtenu beaucoup plus puissant; aujourd'hui, nos téléphones mobiles et les tablettes ont dual et quad core architectures et beaucoup de RAM pour aller avec elle, nos ordinateurs de bureau et les serveurs ont souvent 8 ou 16 cœurs, 16 et 32 go de RAM, si nous ne pouvons pas toujours être en mesure d'avoir les deux en respectant le budget et avoir deux postes de travail est rarement utile pour la plupart d'entre nous.

En outre, PHP a été écrit pour les non-programmeur, c'est beaucoup d'amateurs de la langue maternelle. La raison PHP est si facilement adopté est parce que c'est une langue facile à apprendre et à écrire. La raison PHP est tellement fiable aujourd'hui est en raison de la grande quantité de travail qui va dans son design, et chaque décision prise par le groupe PHP. C'est la fiabilité et la grandeur de la garder dans la lumière de tache, après toutes ces années; d'où ça rivaux ont chuté à un moment ou à pression.

Multi-thread de programmation n'est pas facile pour la plupart, même avec la plus cohérente et fiable de l'API, il ya différentes choses à penser, et de nombreuses idées fausses. Le groupe PHP ne souhaitez pas que l'utilisateur des terres multi-threading de cœur, il n'a jamais été sérieusement prises en compte - et à juste titre. PHP ne doit pas être complexe, pour tout le monde.

Toutes choses considérées, il y a toujours des avantages de PHP permettant de l'utiliser de la production du prêt et testé fonctions pour permettre à un moyen de tirer le meilleur parti de ce que nous avons, lors de l'ajout de plus n'est pas toujours une option, et pour beaucoup de tâches n'est jamais vraiment besoin.

pthreads réalise, pour ceux qui souhaitent explorer, une API qui permet à un utilisateur de multi-thread applications PHP. C'est l'API est très bien d'un travail en cours, et désigné un bêta niveau de la stabilité et de l'exhaustivité.

Il est de notoriété publique que certains des bibliothèques PHP utilise ne sont pas thread-safe, il devrait être clair pour le programmeur que pthreads ne peut pas changer cela, et ne tente pas d'essayer. Toutefois, si une bibliothèque est thread-safe est utilisable, comme dans toute autre thread-safe de l'installation de l'interprète.

pthreads utilise des Threads Posix ( même sous Windows ), ce que le programmeur crée sont de véritables threads d'exécution, mais pour ces fils pour être utile, il doit être conscient de PHP en mesure d'exécuter le code de l'utilisateur, partager des variables et permettent un utile moyen de communication ( synchronisation ). Ainsi, chaque thread est créé avec une instance de l'interpréteur, mais de par sa conception, il est interprète est isolé de tous les autres instances de l'interprète - tout comme le multi-thread Server API environnements. pthreads tente de combler le fossé en une saine et sûre. Bon nombre des préoccupations de la programmation des threads en C ne sont simplement pas là pour le programmeur de pthreads, de par leur conception, les pthreads est de copier sur la lecture et la copie sur écriture ( RAM n'est pas cher ), donc pas de deux instances jamais manipuler les mêmes données physiques, mais ils sont susceptibles d'affecter les données dans un autre thread. Le fait que PHP peut utiliser le thread dangereux des entités de base de la programmation est totalement hors de propos, des threads utilisateur, et il est complètement sûr.

Pourquoi copier sur la lecture et la copie sur écriture:

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

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

(1) à Tout moment de lecture et d'écriture de verrouillage sont organisés sur les pthreads objet de banque de données, les données sont copiées à partir de son emplacement d'origine dans la mémoire pour le magasin d'objets. pthreads ne permet pas de régler le refcount de la variable, Zend est capable de libérer les données d'origine si il n'y a pas d'autres références.

(2) L'argument de someOperation références, le magasin d'objet, l'origine des données stockées, qui elle-même une copie du résultat de (1), est copié à nouveau pour le moteur dans un conteneur zval, alors que cela se produit un verrou en lecture est tenue sur le magasin d'objets, le verrou est libéré et le moteur peut exécuter la fonction. Lorsque l'attribut est créé, il a un refcount de 0, ce qui permet au moteur pour libérer de la copie à la fin de l'opération, parce que pas d'autres références existent.

(3) Le dernier argument de preg_match des références de la banque de données, un verrou de lecture est obtenue, l'ensemble de données en (1) est copié dans une zval, à nouveau avec un refcount de 0. Le verrou est libéré, L'appel à preg_match fonctionne sur une copie des données, qui est lui-même une copie de l'original de données.

Choses à savoir:

  • Le magasin d'objets de la table de hachage où les données sont stockées, thread-safe, est
    basé sur le TsHashTable livré avec PHP, par Zend.

  • Le magasin d'objets a une lecture et d'écriture de verrouillage, d'un accès supplémentaire de verrouillage est prévu pour le TsHashTable tels que si ( et il n', var_dump/print_r, un accès direct aux propriétés que le moteur PHP veut de référence ) pthreads peut manipuler les TsHashTable à l'extérieur de l'API.

  • Les verrous ne sont pas seulement pendant le temps de la copie des opérations ont lieu, lorsque les copies ont été faites les verrous sont relâchés, et dans un ordre logique.

Cela signifie:

  • Quand l'écriture se produit, non seulement sont d'une lecture et d'écriture d'un verrou, mais un supplémentaire de verrouillage d'accès. La table elle-même est verrouillé, il n'est pas façon possible un autre contexte peut se verrouiller, de lire, d'écrire ou de l'affecter.

  • Lors d'une lecture se produit, non seulement est le verrou en lecture de la tenue, mais la supplémentaire de verrouillage d'accès trop, de nouveau, la table est verrouillée.

Pas de deux contextes peuvent physiquement, ni d'accéder simultanément aux mêmes données de la banque d'objet, mais écrit faite dans n'importe quel contexte, avec une référence affectera les données lues dans n'importe quel contexte avec une référence.

C'est sans partage de l'architecture et la seule façon d'exister est co-exister. Ces un peu de jugeote allons voir que, il y a beaucoup de copie se passe ici, et ils vont me demande si c'est une bonne chose. Beaucoup de la copie se passe à l'intérieur d'une dynamique de l'exécution, c'est la dynamique d'un langage dynamique. pthreads est mise en place au niveau de l'objet, parce qu'un bon de commande peut être acquise sur un objet, mais des méthodes - le code, le programmeur exécute - ont un autre contexte, libre de verrouillage et de copies - le local de la portée de la méthode. La portée de l'objet dans le cas d'un pthreads objet doit être considérée comme un moyen de partager des données entre les contextes, c'est que c'est le but. Avec cela à l'esprit, vous pouvez adopter des techniques pour éviter le blocage de l'objet en magasin, sauf si c'est nécessaire, telles que la transmission locale de la portée des variables à d'autres méthodes dans un filet d'objet plutôt que d'avoir leur copie à partir du magasin d'objets lors de l'exécution.

La plupart des bibliothèques et extensions PHP sont minces wrappers autour de 3 parties, PHP de base de la fonctionnalité d'un diplôme est la même chose. pthreads n'est pas une mince wrapper autour de Threads Posix; c'est un filetage API basée sur les Threads Posix. Il n'y a pas de point dans la mise en oeuvre des Threads en PHP que c'est les utilisateurs ne comprennent pas ou ne peut pas utiliser. Il n'y a pas de raison qu'une personne n'ayant aucune connaissance de ce qu'est un mutex est ou ne devrait pas être en mesure de profiter de tout ce qu'ils ont, à la fois en termes de compétences et de ressources. Une fonctions de l'objet comme un objet, mais dans deux contextes autrement seraient en conflit, pthreads donne de la stabilité et de la sécurité.

Quiconque a travaillé dans java va voir les similitudes entre un pthreads objet et le filetage en java, ces mêmes personnes auront sans doute vu une erreur que l'on appelle ConcurrentModificationException - comme il sonne une erreur provoquée par le java runtime si deux threads écrire les mêmes données en même temps. Je comprends pourquoi il existe, mais il me déroute que grâce à des moyens aussi bas qu'ils le sont, couplé avec le fait que l'exécution est en mesure de détecter la concurrence d'accès à l'exacte et seulement le temps que la sécurité pourrait être atteint pour l'utilisateur, qu'il choisit de lancer une éventuelle erreur fatale lors de l'exécution plutôt que de gérer l'exécution et l'accès aux données.

Aucune de ces erreurs stupides seront émis par les pthreads, l'API est écrit pour faire enfiler comme stable et compatible que possible, je crois.

Le Multi-threading n'est pas à l'utilisation d'une nouvelle base de données, une attention particulière devrait être accordée à chaque mot dans le manuel et les exemples livrés avec des pthreads.

Enfin, sur le manuel PHP:

pthreads a été, et est, une expérience avec d'assez bons résultats. L'un de ses limites ou les caractéristiques peuvent changer à tout moment; c'est la nature de l'expérimentation. Ses limites - souvent imposés par la mise en œuvre existent pour une bonne raison; le but de pthreads est de fournir une solution utilisable pour le multi-tâches en PHP à tout niveau. Dans l'environnement, qui pthreads exécute, certaines restrictions et limitations sont nécessaires afin de fournir un environnement stable.

48voto

Darryl Hein Points 33819

Voici un exemple de ce que Wilco a suggéré:

$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);

En gros, cela exécute le script PHP en ligne de commande, mais retourne le PID, puis exécute en arrière-plan. (L'echo de $! garantit rien d'autre n'est retourné autre que le PID.) Cela permet à votre script PHP pour continuer ou arrêter si vous le souhaitez. Lorsque je l'ai utilisé, j'ai redirigé l'utilisateur vers une autre page, où tous les 5 à 60 secondes un appel AJAX est fait pour vérifier si le rapport est toujours en cours d'exécution. (J'ai une table pour stocker les gen_id et l'utilisateur c'est lié.) La vérification de script s'exécute les opérations suivantes:

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

Il y a un post sur cette technique ici: http://nsaunders.wordpress.com/2007/01/12/running-a-background-process-in-php/

40voto

Wilco Points 10838

Il n’y a rien de disponible que je connais. La prochaine meilleure chose serait d’avoir simplement un script exécuter un autre via CLI, mais c’est un peu rudimentaire. Selon ce que vous essayez de le faire et c’est la complexité, cela peut ou peut ne pas être une option.

25voto

Francois Bourgeois Points 1277

En bref: oui, il y a le multithreading en php, mais vous devez utiliser le multitraitement à la place.

Fond d'écran info: threads vs processus

Il y a toujours un peu de confusion à propos de la distinction de threads et de processus, donc je vais brièvement décrire à la fois:

  • Un thread est une séquence de commandes à l'unité. Les seules données, il se compose d'un compteur de programme. Chaque cœur de PROCESSEUR ne traite que d'un fil à la fois, mais vous pouvez basculer entre l'exécution d'êtres différents par la planification.
  • Un processus est un ensemble de ressources partagées. Cela signifie qu'il est constitué d'une partie de la mémoire, des variables, des instances de l'objet, les descripteurs de fichiers, mutex, de connexions de base de données et ainsi de suite. Chaque processus contient également un ou plusieurs threads. Tous les threads d'un même processus partagent ses ressources, de sorte que vous pouvez utiliser une variable dans un thread que vous avez créé à l'autre. Si les threads sont des parties de deux processus différents, alors ils ne peuvent pas l'accès des uns et des autres ressources directement. Dans ce cas, vous avez besoin de communication inter-processus , par exemple par des tuyaux, des fichiers, sockets...

Multitraitement

Vous pouvez réaliser le calcul parallèle par la création de nouveaux processus (qui contiennent aussi un nouveau thread) avec php. Si votre fils n'a pas besoin de beaucoup de communication ou de synchronisation, c'est votre choix, car les processus sont isolés et ne peuvent pas interférer avec le travail de chacun. Même si on se plante, qui ne concerne pas les autres. Si vous avez besoin d'une bonne communication, vous devriez lire à "multithreading" ou - malheureusement - envisager d'utiliser un autre langage de programmation, parce que la communication inter-processus de synchronisation et introduit beaucoup de teint.

En php, vous avez deux façons de créer un nouveau processus:

laissez le système d'exploitation le faire pour vous: vous pouvez dire à votre système d'exploitation pour créer un nouveau processus et de lancer un nouveau (ou le même) script php.

  • pour linux , vous pouvez utiliser les méthodes suivantes, ou envisager de Darryl Hein réponse:

    $cmd = 'nice php script.php 2>&1 & echo $!';
    pclose(popen($cmd, 'r'));
    
  • pour windows , vous pouvez utiliser ceci:

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

faire vous-même avec une fourchette: php fournit également la possibilité d'utiliser un fork par le biais de la fonction pcntl_fork(). Un bon tutoriel sur la façon de faire ce qui peut être trouvé ici, mais je vous recommande fortement de ne pas l'utiliser, car la fourche est un crime contre l'humanité et en particulier à l'encontre de la poo.

Le Multithreading

Avec le multithreading tous vos threads partagent leurs ressources, de sorte que vous pouvez facilement communiquer entre et de les synchroniser, sans beaucoup de frais généraux. De l'autre côté, vous devez savoir ce que vous faites, puisque les conditions de course et les blocages sont faciles à produire, mais très difficile à déboguer.

Standard de php ne fournit pas de multithreading, mais il y a un (expérimental) extension qui ne fait - pthreads. Sa documentation de l'api, même dans php.net. Avec elle, vous pouvez faire quelques trucs que vous pouvez dans de vrais langages de programmation :-) comme ceci:

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();
}

Pour linux il y a un guide d'installation ici à stackoverflow.

Pour windows il y en a un maintenant:

  • D'abord vous avez besoin de la version thread-safe de php.
  • Vous avez besoin de la pré-versions compilées des deux pthreads et son extension php. Ils peuvent être téléchargés ici. Assurez-vous de télécharger la version qui est compatible avec votre version de php.
  • Copie php_pthreads.dll (à partir du zip que vous venez de télécharger) dans votre php extension de dossier ([phpDirectory]/ext).
  • Copie pthreadVC2.dll dans [phpDirectory] (le dossier racine - pas le dossier de l'extension).
  • Edit [phpDirectory]/php.ini et insérez la ligne suivante

    extension=php_pthreads.dll
    
  • Test avec le script ci-dessus avec un peu de sommeil ou quelque chose là où le commentaire est.

Et maintenant le grand MAIS: Bien que cela fonctionne vraiment, php n'était pas à l'origine faite pour le multithreading. Il existe une version thread-safe de php et de la v5.4 il semble être à peu près exempt de bogues, mais à l'aide de php dans un environnement multi-thread est encore découragé dans le manuel php (mais peut-être qu'ils n'ont pas mis à jour son manuel sur ce, encore). Un problème beaucoup plus important peut-être que beaucoup de communes extensions ne sont pas thread-safe. Alors vous pourriez obtenir des threads avec cette extension php, mais les fonctions que vous êtes en fonction sur sont toujours pas thread-safe, vous aurez probablement rencontrer des conditions de course, les blocages et ainsi de suite dans le code, vous n'avez pas écrit vous-même...

17voto

davr Points 9556

Vous pouvez utiliser pcntl_fork() pour réaliser quelque chose de similaire aux threads. Techniquement, c’est des processus distincts, alors la communication entre les deux n’est pas aussi simple avec les threads, et je crois que cela ne fonctionnera pas si PHP est appelé par apache.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X