pthreads

Introduction

pthreads est une API orientée objet qui apporte tous les outils nécessaires pour le multithreading en PHP. Les applications PHP peuvent créer, lire, écrire, exécuter et synchroniser des Threads, des Workers, et des objets Threaded.

Avertissement

Cette extension est considérée non maintenue et morte.

Astuce

Envisager d'utiliser parallel à la place.

Avertissement

L'extension pthreads ne peut pas être utilisée dans un environnement de serveur Web. Le Threading en PHP est donc limité aux applications basées sur CLI uniquement.

Avertissement

pthreads (v3) peut être utilisé uniquement avec PHP 7.2+ à cause d'un mode ZTS dangereux en PHP 7.0 et 7.1.

La classe Threaded constitue la base de la fonctionnalité qui permet à pthreads de fonctionner. Il expose les méthodes de synchronisation et quelques interfaces utiles pour le programmeur.

La classe Thread permet de créer des threads en l'étendant simplement et en implémentant une méthode run. Tous les membres peuvent être écrits et lus par n'importe quel contexte avec une référence au thread. Tout contexte peut également exécuter toutes les méthodes publiques et protégées. Le corps de la méthode run sera exécuté dans un thread séparé lorsque la méthode Thread::start() de l'implémentation est appelée à partir du contexte qui l'a créé. Seul le contexte qui crée un thread peut le démarrer et le rejoindre.

La classe Worker a un état persistant et sera disponible à partir de l'appel à Thread::start() (une méthode héritée) jusqu'à ce que l'objet soit hors de portée, ou soit explicitement arreté (via Worker::shutdown()). Tout contexte avec une référence à l'objet Worker peut empiler des tâches sur le Worker (via Worker::stack()), où ces tâches seront exécutées par le Worker dans un thread séparé. La méthode run d'un objet worker est exécutée avant tout objet de la pile du worker, ce qui permet aux ressources d'être initialisées pour que les objets à exécuter puissent les utiliser.

La classe Pool est utilisée pour créer un groupe de worker pour distribuer des objets Threaded parmi eux. Il est le moyen le plus facile et le plus efficace d'utiliser plusieurs threads dans les applications PHP.

Attention

La classe Pool n'étend pas la classe Threaded, et donc les objets basés sur pool sont considérés comme des objets PHP normaux. En tant que tel, ses instances ne doivent pas être partagées entre des contextes différents.

La classe Volatile est nouvelle pour pthreads v3. Elle est utilisée pour désigner les propriétés Threaded mutable des classes Threaded (car celles-ci sont désormais immuables par défaut). Elle est également utilisée pour stocker des tableaux PHP dans des contextes Threaded.

La synchronisation est une capacité importante lors du Threading. Tous les objets créés par pthreads ont été construits en synchronisation dans la forme (qui sera familière aux programmeurs Java) de Threaded::wait() et Threaded::notify(). L'appel de Threaded::wait() sur un objet entraînera le contexte à attendre qu'un autre contexte appelle Threaded::notify() sur le même objet. Ce mécanisme permet une synchronisation puissante entre les objets Threaded en PHP.

Attention

Tout objet prévu pour être utilisé dans une partie multithreadé du application doit étendre Threaded.

Stockage des données : En règle générale, tous les types de données pouvant être sérialisés peuvent être utilisés comme membre d'un objet Threadé, ils peuvent être lus, et écrits depuis n'importe quel contexte avec une référence vers l'objet Threadé. Tous les types de données ne sont pas stockés après sérialisation ; les types simples sont stockés sous leur forme initiale. Les types complexes, les tableaux et les objets qui ne sont pas Threadés, sont stockés sérialisés ; ils peuvent être lus et écrits dans l'objet Threadé depuis n'importe quel contexte avec une référence. A l'exception des objets Threadés, toute référence utilisée pour définir un membre d'un objet Threadé est séparé de la référence dans l'objet Threadé ; les mêmes données peuvent être lues directement depuis l'objet Threadé à tout moment par n'importe quel contexte avec une référence vers l'objet Threadé.

Membres statiques : Lorsqu'un nouveau contexte est créé (Thread ou Worker), ils sont généralement copiés, mais les ressources et objects avec un état interne sont nullifiés (pour des raisons de sécurité). Ceci permet alors à la fonction une sorte de stockage local au niveau du thread. Par exemple, lors du démarrage du contexte, une classe dont les membres statiques incluent des informations de connexion vers un serveur de base de données, seules les informations seront copiées, et non la connexion en tant que telle. Ceci permet au nouveau contexte d'initialiser une connexion de la même façon que le contexte qui l'a créé, stockant la connexion au même endroit sans pour autant affecter le contexte original.

Attention

Lorsque print_r, var_dump et d'autres fonctions de débogage sont exécutées, elles n'incluent pas de protection contre la récursion.

Note: Ressources : Les extensions et les fonctionnalités qui définissent des ressoures en PHP ne sont pas préparées pour ce type d'environnement ; pthreads prend des dispositions en matière de ressource à partager entre les contextes, cependant, pour la plupart des ressources, elles devront être considérées comme dangereuses. Un soin et une extrème prudence devront être de mise pour partager les ressources entre les contextes.

Attention

Dans l'environnement d'exécution de pthreads, des restrictions et des limitations sont nécessaires afin de fournir un environnement stable.

add a note

User Contributed Notes 4 notes

up
27
anonymous at example dot com
8 years ago
Here are some notes regarding PHP pThreads v3 that I have gathered:
-namespace: It does not understand namespaces. 
-globals: It won't serialize GLOBALS at all! And will not register new ones.
-classes: It registers new classes okay.
-functions: Will not register ANY functions - they must all be in static classes. It does understand PHP native functions. 
-consts: previous constants will transfer over. Don't make any new ones thou!
-pThreads only work in CLI - of course!
-If a thread crashes it automatically gets recreated.
-In order to 'force kill' any thread the parent must be killed. Or wait until all other tasks queued are complete and then terminate.
-Anything registered in a pThread does not seem to join the main thread ... which is good!
-pThreads seem to be very powerful on multi-core environments, just need to be careful on system resources... it can and will lock up a system if mis-configured.
-Finally, finding help for PHP pThreads is slim to none... especially v3!

Good luck!
up
9
meadowsjared at gmail dot com
5 years ago
In this example, it shows how to use a threaded with a pool to get an array of results, using pThreads v3.2.1 and php 7.3.23

<?php
class TestWork extends Threaded {
//updated version that works with pThreads v3.2.1 and php 7.3.23
    protected $complete;
    //$pData is the data sent to your worker thread to do it's job.
    public function __construct($pData) {
        //transfer all the variables to local variables
        $this->complete = false;
        $this->testData = $pData;
    }
    //This is where all of your work will be done.
    public function run() {
        usleep(2000000); //sleep 2 seconds to simulate a large job
        $this->complete = true;
    }
    public function isDone() {
        return $this->complete;
    }
}
class ExamplePool extends Pool {
    public $data = array(); // used to return data after we're done
    private $numTasks = 0; // counter used to know when we're done
    /**
     * override the submit function from the parent
     * to keep track of our jobs
     */
    public function submit(Threaded $task) {
        $this->numTasks++;
        parent::submit($task);
    }
    /**
     * used to wait until all workers are done
     */
    public function process() {
        // Run this loop as long as we have
        // jobs in the pool
        while (count($this->data) < $this->numTasks) {
            $this->collect(function (TestWork $task) {
                // If a task was marked as done
                // collect its results
                if ($task->isDone()) {
                    $tmpObj = new stdclass();
                    $tmpObj->complete = $task->complete;
                    //this is how you get your completed data back out [accessed by $pool->process()]
                    $this->data[] = $tmpObj;
                }
                return $task->isDone();
            });
        }
        // All jobs are done
        // we can shutdown the pool
        $this->shutdown();
        return $this->data;
    }
}
$pool = new ExamplePool(3);
$testData = 'asdf';
for($i=0;$i<5;$i++) {
    $pool->submit(new TestWork($testData));
}
$retArr = $pool->process(); //get all of the results
echo '<pre>';
print_r($retArr); //return the array of results (and maybe errors)
echo '</pre>';
?>
up
9
jasonrlester at yahoo dot com
12 years ago
Note that this extension *is* a high level implementation of POSIX threads, including on Windows (which is why pthreadsV*.dll is required)
up
6
admin at deosnet dot com
11 years ago
Hello,

WARNING : When using Stackable objects in callable functions by your Threads, you must be very careful if you use it as an array. Indeed, if you do not copy your Stackable "array" in a local variable, the execution time can drop drastically !

Also, if you want to modify an array() in a function, you will also store in a local variable in order that your array is in a thread-safe context.
To Top