pthreads

Introducción

pthreads es una API orientada a objetos que aporta todas las herramientas necesarias para el multithreading en PHP. Las aplicaciones PHP pueden crear, leer, escribir, ejecutar y sincronizar Threads, Workers, y objetos Threaded.

Advertencia

Esta extensión es considerada no mantenida y obsoleta.

Sugerencia

Considerar el uso de parallel en su lugar.

Advertencia

La extensión pthreads no puede ser utilizada en un entorno de servidor Web. El threading en PHP se limita por tanto a aplicaciones basadas en CLI únicamente.

Advertencia

pthreads (v3) puede ser utilizado únicamente con PHP 7.2+ debido a un modo ZTS peligroso en PHP 7.0 y 7.1.

La clase Threaded constituye la base de la funcionalidad que permite a pthreads funcionar. Expone los métodos de sincronización y algunas interfaces útiles para el programador.

La clase Thread permite crear threads extendiéndola simplemente e implementando un método run. Todos los miembros pueden ser escritos y leídos por cualquier contexto con una referencia al thread. Todo contexto puede igualmente ejecutar todos los métodos públicos y protegidos. El cuerpo del método run será ejecutado en un thread separado cuando el método Thread::start() de la implementación sea llamado desde el contexto que lo creó. Solo el contexto que crea un thread puede iniciarlo y unirse a él.

La clase Worker tiene un estado persistente y estará disponible desde la llamada a Thread::start() (un método heredado) hasta que el objeto esté fuera de alcance, o sea explícitamente detenido (vía Worker::shutdown()). Todo contexto con una referencia al objeto Worker puede apilar tareas en el Worker (vía Worker::stack()), donde estas tareas serán ejecutadas por el Worker en un thread separado. El método run de un objeto worker es ejecutado antes de cualquier objeto de la pila del worker, lo que permite que los recursos sean inicializados para que los objetos a ejecutar puedan usarlos.

La clase Pool se utiliza para crear un grupo de workers para distribuir objetos Threaded entre ellos. Es el medio más fácil y eficiente de utilizar múltiples threads en aplicaciones PHP.

Precaución

La clase Pool no extiende la clase Threaded, y por tanto los objetos basados en pool son considerados como objetos PHP normales. En consecuencia, sus instancias no deben ser compartidas entre contextos diferentes.

La clase Volatile es nueva para pthreads v3. Se utiliza para designar las propiedades Threaded mutables de las clases Threaded (ya que estas son ahora inmutables por defecto). También se utiliza para almacenar arrays PHP en contextos Threaded.

La sincronización es una capacidad importante al realizar threading. Todos los objetos creados por pthreads han sido construidos con sincronización en la forma (que será familiar a los programadores Java) de Threaded::wait() y Threaded::notify(). La llamada a Threaded::wait() sobre un objeto hará que el contexto espere a que otro contexto llame a Threaded::notify() sobre el mismo objeto. Este mecanismo permite una sincronización poderosa entre los objetos Threaded en PHP.

Precaución

Todo objeto previsto para ser utilizado en una parte multithread de la aplicación debe extender Threaded.

Almacenamiento de datos: En regla general, todos los tipos de datos que puedan ser serializados pueden ser utilizados como miembro de un objeto Threaded, pueden ser leídos y escritos desde cualquier contexto con una referencia al objeto Threaded. No todos los tipos de datos son almacenados después de la serialización; los tipos simples son almacenados en su forma inicial. Los tipos complejos, los arrays y los objetos que no son Threaded, son almacenados serializados; pueden ser leídos y escritos en el objeto Threaded desde cualquier contexto con una referencia. A excepción de los objetos Threaded, toda referencia utilizada para definir un miembro de un objeto Threaded es separada de la referencia en el objeto Threaded; los mismos datos pueden ser leídos directamente desde el objeto Threaded en cualquier momento por cualquier contexto con una referencia al objeto Threaded.

Miembros estáticos: Cuando un nuevo contexto es creado (Thread o Worker), generalmente son copiados, pero los recursos y objetos con estado interno son nullificados (por razones de seguridad). Esto permite a la función una especie de almacenamiento local a nivel de thread. Por ejemplo, al iniciar el contexto, una clase cuyos miembros estáticos incluyen información de conexión a un servidor de base de datos, solo la información será copiada, y no la conexión en sí. Esto permite al nuevo contexto inicializar una conexión de la misma forma que el contexto que lo creó, almacenando la conexión en el mismo lugar sin afectar al contexto original.

Precaución

Cuando print_r, var_dump y otras funciones de depuración son ejecutadas, no incluyen protección contra la recursión.

Nota: Recursos: Las extensiones y funcionalidades que definen recursos en PHP no están preparadas para este tipo de entorno; pthreads toma disposiciones en materia de recursos a compartir entre los contextos, sin embargo, para la mayoría de los recursos, deberán ser considerados como peligrosos. Un cuidado y una extrema precaución deberán ser de aplicación para compartir recursos entre los contextos.

Precaución

En el entorno de ejecución de pthreads, restricciones y limitaciones son necesarias para proporcionar un entorno estable.

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