pthreads

Введение

pthreads предоставляет объектно-ориентированный API для работы с многопоточностью в PHP. Приложения на PHP могут создавать, читать, записывать, запускать и выполнять синхронизацию с объектами Threads, Workers и Threaded.

Внимание

Модуль считается неподдерживаемым и мёртвым.

Подсказка

Попробуйте вместо этого использовать parallel.

Внимание

Модуль доступен только для CLI-приложений. Исходя из этого, многопоточность в PHP в окружении веб-сервера недоступна.

Внимание

pthreads (v3) может использоваться только с PHP 7.2 и выше, так как ZTS-режим нестабилен в 7.0 и 7.1.

Класс Threaded предоставляет базовый функционал, необходимый для работы pthreads. Он предоставляет методы синхронизации и некоторые полезные для разработчика интерфейсы.

Класс Thread позволяет создавать потоки. Для создания потока необходимо создать наследующие его класс и в нём реализовать метод run. Любые свойства могут быть записаны и прочитаны из любого контекста через ссылку на поток. Также из любого контекста могут быть вызваны публичные и защищённые методы. Метод run будет запущен в отдельном потоке, как только будет вызван метод Thread::start() из контекста, в котором он был создан. Стартовать и присоединить поток можно только в том контексте, где он был создан.

Класс Worker имеет постоянное состояние и будет доступен из метода Thread::start() (унаследованный метод) до тех пор, пока объект не выйдет из области видимости, либо пока не будет принудительно остановлен (с помощью Worker::shutdown()). Любой контекст имеющий ссылку к данному объекту может добавлять задания на стек Worker (с помощью Worker::stack()), которые будут запущены в отдельном потоке. Метод run объекта Worker будет запущен раньше, чем любой объект с его стека задач, что даёт возможность инициализировать необходимые для задачи ресурсы.

Класс Pool используется для создания группы исполнителей (worker) для распределения между ними объектов Threaded. Это самый простой и эффективный вариант использования многопоточности в PHP.

Предостережение

Класс Pool не наследует Threaded, таким образом являясь обычным объектом PHP. Объекты этого класса не должны разделяться по различным контекстам.

Класс Volatile добавлен в pthreads v3. Он используется для задания изменяемых Threaded-свойств классов типа Threaded (так как теперь они по умолчанию неизменяемы). Также используется для хранения массивов PHP в контексте Threaded.

Синхронизация - важная часть многопоточности. Все объекты, созданные pthreads, имеют встроенные методы для обеспечения синхронизации (они покажутся очень знакомыми для разработчиков на Java): Threaded::wait() и Threaded::notify(). Вызов Threaded::wait() переведёт объект в ожидание до того момента, пока из другого контекста не будет вызван Threaded::notify() для ожидающего объекта. Этот механизм позволяет осуществлять синхронизацию между объектами Threaded.

Предостережение

Любые объекты вашего приложения, которые предполагается использовать в многопоточном режиме, должны наследовать Threaded.

Хранение данных: Как правило, в объекте Threaded можно использовать любые данные, которые могут быть сериализованы. Они могут быть записаны и прочтены из любого контекста через ссылку на этот объект. Не каждый тип данных хранится в сериализованном виде. Базовые типы хранятся в их истинной форме. Сложные типы, массивы и объекты , не являющиеся Threaded, хранятся сериализованными; они могут быть прочитаны или записаны в Threaded-объект из любого контекста по ссылке. За исключением Threaded-объектов, все ссылки, использующиеся для установки свойства в Threaded-объекте отделены от ссылок внутри Threaded-объекте. Чтение тех же данных можно производить напрямую из любого контекста по ссылке на Threaded-объекте.

Статические свойства: Когда создаётся новый контекст (Thread или Worker), они просто копируются, но ресурсы и объекты обнуляются (из соображения безопасности). Это позволяет использовать их как локальные для потока хранилища. К примеру, во время создания контекста, для класса, статические свойства которого хранят информацию о соединении к БД и само соединение, будет скопирована только информация необходимая для соединения, но не само соединение. Это позволит создать новое соединение в новом контексте и сохранить его в том же месте никак не затрагивая оригинальный контекст.

Предостережение

Когда запускаются print_r, var_dump или другие отладочные функции, они не включают защиту от рекурсии.

Замечание: Ресурсы: Модули и функциональность PHP, создающие ресурсы, совершенно не подготовлены для такого типа окружения; pthreads предоставляет механизм разделения ресурсов между контекстами, однако для большинства типов ресурсов его следует считать небезопасным. Разделяя ресурс между контекстами необходимо быть крайне внимательным и осторожным.

Предостережение

В окружении, где запускается pthreads, необходимы некоторые ограничения и запреты для обеспечения стабильности.

Добавить

Примечания пользователей 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