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. Elle 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 arrĂȘtĂ© (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Ă©e de l'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. À l'exception des objets ThreadĂ©s, toute rĂ©fĂ©rence utilisĂ©e pour dĂ©finir un membre d'un objet ThreadĂ© est sĂ©parĂ©e 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 objets 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 ressources 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
29
anonymous at example dot com ¶
9 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
10
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.