pthreads-это объектно-ориентированный API, который предоставляет все инструменты, необходимые для многопоточности в PHP. PHP приложения могут создавать, читать, писать, выполнять и синхронизировать с потоками, рабочими и потоковыми объектами.
Расширение pthreads нельзя использовать в среде веб-сервера. Поэтому потоки в PHP ограничены только приложениями на основе CLI.
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()), где эти задачи будут выполняться worker в отдельном потоке. Метод 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 в PHP.
Любые объекты, которые предназначены для использования в многопоточных частях вашего приложения, должны расширять Threaded.
Хранение данных: как правило, любой тип данных, который может быть сериализован, может использоваться в качестве члена потокового объекта, он может быть прочитан и записан из любого контекста со ссылкой на потоковый объект. Не каждый тип данных хранится последовательно, основные типы хранятся в их истинном виде. Сложные типы, массивы и объекты, не являющиеся потоковыми, хранятся последовательно; они могут считываться и записываться в потоковый объект из любого контекста со ссылкой. За исключением потоковых объектов, любая ссылка, используемая для задания члена потокового объекта, отделяется от ссылки в потоковом объекте; те же данные могут быть считаны непосредственно из потокового объекта в любое время любым контекстом со ссылкой на потоковый объект.
Статические члены: когда создается новый контекст (поток или рабочий), они обычно копируются, но ресурсы и объекты с внутренним состоянием обнуляются (по соображениям безопасности). Это позволяет им функционировать как своего рода локальное хранилище потоков. Например, при запуске контекста класс, статические члены которого содержат сведения о соединении для сервера базы данных, а также само соединение, будет иметь только простые сведения о соединении, а не о соединении. Позволяет новому контексту инициировать соединение таким же образом, как и контекст, создавший его, сохраняя соединение в том же месте, не затрагивая исходный контекст.
При выполнении функций отладки print_r, var_dump и других объектов они не включают защиту рекурсии.
Замечание:
Ресурсы: расширения и функциональные возможности, которые определяют ресурсы в PHP, совершенно неподготовлены для такого рода среды; pthreads предусматривает, что ресурсы должны быть разделены между контекстами, однако для большинства типов ресурсов это должно считаться небезопасным. При распределении ресурсов между контекстами следует проявлять крайнюю осторожность и осторожность.
В среде, которую выполняет pthreads, некоторые ограничения и ограничения необходимы для обеспечения стабильной среды.
Предопределенные константы
Перечисленные ниже константы определены данным расширением и могут быть доступны только в том случае, если PHP был собран с поддержкой этого расширения или же в том случае, если данное расширение было подгружено во время выполнения.
PTHREADS_INHERIT_ALL
(integer)- Параметры по умолчанию для всех потоков приводят к тому, что pthreads копирует среду при запуске новых потоков.
PTHREADS_INHERIT_NONE
(integer)- Не наследовать ничего при запуске новых потоков
PTHREADS_INHERIT_INI
(integer)- Наследовать записи INI при запуске новых потоков
PTHREADS_INHERIT_CONSTANTS
(integer)- Наследовать объявленные пользователем константы при запуске новых потоков
PTHREADS_INHERIT_CLASSES
(integer)- Наследовать объявленные пользователем классы при запуске новых потоков
PTHREADS_INHERIT_FUNCTIONS
(integer)- Наследовать объявленные пользователем функции при запуске новых потоков
PTHREADS_INHERIT_INCLUDES
(integer)- Наследовать включенную информацию о файле при запуске новых потоков
PTHREADS_INHERIT_COMMENTS
(integer)- Наследовать все комментарии при запуске новых потоков
PTHREADS_ALLOW_HEADERS
(integer)- Разрешить новым потокам отправлять заголовки в стандартный вывод (обычно запрещено)
Вот некоторые заметки, касающиеся PHP pThreads v3, которые я собрал:
-namespace: Он не понимает пространства имен.
-globals: Он не будет сериализовать GLOBALS вообще! И не буду регистрировать новые.
-classes: Он регистрирует новые классы хорошо.
-functions: Не будет регистрировать ЛЮБЫЕ функции - все они должны быть в статических классах. Он понимает родные функции PHP.
-consts: предыдущие константы будут перенесены. Не делай новых!
-pThreads работает только в CLI - конечно!
-Если поток падает, он автоматически воссоздается.
-Чтобы принудительно уничтожить любой поток, родитель должен быть уничтожен. Или дождитесь завершения всех других задач, поставленных в очередь, а затем завершите работу.
-Все, что зарегистрировано в pThread, похоже, не присоединяется к основному потоку ... это хорошо!
-pThreads кажется очень мощным на многоядерных средах, просто нужно быть осторожным на системных ресурсах... он может и будет блокировать систему, если неправильно настроен.
-Наконец, поиск справки для PHP pThreads сведен к нулю... особенно v3!
Обратите внимание, что это расширение является реализацией высокого уровня потоков POSIX, в том числе в Windows (именно поэтому требуется pthreadsV *.dll)
ВНИМАНИЕ: При использовании Stackable объектов в вызываемых функциях вашими потоками, вы должны быть очень осторожны, если используете его как массив. Действительно, если вы не скопируете свой Stackable «массив» в локальную переменную, время выполнения может резко упасть!
Также, если вы хотите изменить array () в функции, вы также сохраните ее в локальной переменной, чтобы ваш массив находился в поточно-ориентированном контексте.
Если вы пытаетесь проверить многопоточность, не забудьте позволить php думать медленно:
<?php class My extends Thread{ function run(){ for($i=1;$i<10;$i++){ echo Thread::getCurrentThreadId() . "\n"; sleep(2); // <------ } } } for($i=0;$i<2;$i++){ $pool[] = new My(); } foreach($pool as $worker){ $worker->start(); } foreach($pool as $worker){ $worker->join(); } ?>
6300 5816 6300 5816 6300 5816 6300 5816 6300 5816 6300 5816 6300 5816 6300 5816 6300 5816
Если вы отключите функцию sleep(), процессное время для потоков будет достаточно длинным, чтобы завершить сценарий сразу.