Я обнаружил, что этот пакет PECL называется потоками , но пока нет релиза. И на веб-сайте PHP ничего не происходит.
Я ничего не знаю об этом. Следующим лучшим было бы просто, чтобы один скрипт выполнял другой через CLI, но это немного рудиментарно. В зависимости от того, что вы пытаетесь сделать и насколько это сложно, это может быть или не быть вариантом.
Из руководства по PHP для расширения pthreads :
pthreads – это ориентированный на объект API, который позволяет многопоточность пользовательского доступа в PHP. Он включает в себя все инструменты, необходимые для создания многопоточных приложений, ориентированных на Интернет или консоль. Приложения PHP могут создавать, читать, писать, исполнять и синхронизировать с Threads, Workers и Stackables.
Как это ни удивительно, это совершенно верно. Сегодня PHP может многопоточно для тех, кто хочет попробовать.
Первый выпуск PHP4, 22 мая 2000 г., PHP был снабжен архитектурой с потоковой безопасностью – возможностью запуска нескольких экземпляров своего интерпретатора в отдельных потоках в многопоточных средах SAPI (Server API). За последние 13 лет дизайн этой архитектуры поддерживается и развит: с тех пор он используется на крупнейших мировых сайтах.
Потоки на земле пользователя никогда не вызывали беспокойства для команды PHP, и сегодня она остается такой же. Вы должны понимать, что в мире, где PHP работает, существует уже определенный метод масштабирования – добавьте оборудование. За многие годы существования PHP, аппаратное обеспечение стало дешевле и дешевле, и поэтому это становилось все менее и менее озабоченным для команды PHP. Хотя он стал дешевле, он также стал намного более мощным; сегодня наши мобильные телефоны и планшеты имеют двухъядерные и четырехъядерные архитектуры и много оперативной памяти, и наши настольные компьютеры и серверы обычно имеют 8 или 16 ядер, 16 и 32 гигабайта оперативной памяти, хотя мы не всегда можем иметь два в бюджете и с двумя рабочими столами редко бывает полезной для большинства из нас.
Кроме того, PHP был написан для не-программиста, это много любителей родного языка. Причина, по которой PHP настолько легко принимается, заключается в том, что это простой язык для изучения и записи. Причина, по которой PHP настолько надежна сегодня, объясняется огромным количеством работы, которая входит в ее дизайн, и каждым решением, принятым группой PHP. После всех этих лет надежность и чистота сохраняют ее на свету; где это соперники упали до времени или давления.
Многопоточное программирование непросто для большинства, даже с самым последовательным и надежным API, есть разные вещи, о которых нужно думать, и о многих заблуждениях. Группа PHP не хочет, чтобы многопоточность пользовательских наземных многопотоков была основной особенностью, ей никогда не уделялось серьезного внимания – и это правильно. PHP не должен быть сложным, для всех.
Учитывая все обстоятельства, все еще есть преимущества, позволяющие PHP использовать его готовые и проверенные функции для производства, чтобы обеспечить максимальную отдачу от того, что у нас есть, когда добавление большего не всегда является опцией и для многих задач никогда не требуется.
pthreads позволяет тем, кто хочет исследовать его, API, который позволяет пользователю использовать многопоточные приложения PHP. Это API – это очень большая работа, и он обозначил уровень стабильности и полноты бета-версии.
Общеизвестно, что некоторые из библиотек, использующих PHP, не являются потокобезопасными, должно быть понятно программисту, что pthreads не могут изменить это и не пытаются попробовать. Тем не менее, любая библиотека, которая является потокобезопасной, может использоваться, как и в любой другой потоковой безопасной установке интерпретатора.
pthreads использует Posix Threads (даже в Windows), то, что создает программист, являются реальными потоками исполнения, но для того, чтобы эти потоки были полезными, они должны знать PHP – возможность выполнять код пользователя, обмениваться переменными и предоставлять полезные средства связи (синхронизация). Таким образом, каждый поток создается экземпляром интерпретатора, но по дизайну его интерпретатор изолирован от всех других экземпляров интерпретатора – точно так же, как многопоточные серверные API-интерфейсы. pthreads пытается свести разрыв в разумный и безопасный путь. Многие из проблем программиста потоков в C просто не существуют для программиста pthreads, по дизайну, pthreads является копией на чтение и копирование при записи (оперативная память дешевая), поэтому никакие два экземпляра никогда не манипулируют одними и теми же физическими данными , но они могут влиять на данные в другом потоке. Тот факт, что PHP может использовать небезопасные функции потока в его основном программировании, совершенно не имеет значения, пользовательские потоки, и его операции полностью безопасны.
Зачем копировать на чтение и копирование при записи:
public function run() { ... (1) $this->data = $data; ... (2) $this->other = someOperation($this->data); ... } (3) echo preg_match($pattern, $replace, $thread->data);
(1) Хотя блокировки чтения и записи хранятся в хранилище данных объекта pthreads, данные копируются из исходного местоположения в память в хранилище объектов. pthreads не корректирует пересчет переменной, Zend может освобождать исходные данные, если дальнейших ссылок на нее нет.
(2) Аргумент someOperation ссылается на хранилище объектов, исходные данные, которые он сам копирует результат (1), снова копируется для двигателя в контейнер zval, в то время как это происходит, блокировка чтения сохраняется хранилище объектов, блокировка освобождается, и двигатель может выполнять функцию. Когда zval создается, он имеет значение 0, позволяя движку освобождать копию при завершении операции, поскольку никаких других ссылок на нее не существует.
(3) Последний аргумент для preg_match ссылается на хранилище данных, получается блокировка чтения, набор данных в (1) копируется в zval, опять же с refcount of 0. Блокировка освобождается, вызов preg_match работает копия данных, которая сама является копией исходных данных.
Что нужно знать:
Хэш-таблица хранилища объектов, в которой хранятся данные, потокобезопасна,
основанный на TsHashTable, поставляемом с PHP, Zend.
В хранилище объектов есть блокировка чтения и записи, для TsHashTable предусмотрена дополнительная блокировка доступа, которая требует (и, как правило, var_dump / print_r, прямого доступа к свойствам, так как движок PHP хочет ссылаться на них). Pthreads могут манипулировать TsHashTable вне определенного API.
Блокировки удерживаются только во время операций копирования, когда копии были сделаны, блокировки освобождаются в разумном порядке.
Это означает:
Когда происходит запись, сохраняется не только блокировка чтения и записи, но и дополнительная блокировка доступа. Сама таблица заблокирована, нет другого способа, которым другой контекст может блокировать, читать, писать или влиять на него.
Когда происходит чтение, сохраняется не только блокировка чтения, но и дополнительная блокировка доступа, опять же таблица заблокирована.
Ни один из двух контекстов не может физически или одновременно обращаться к тем же данным из хранилища объектов, но записи, сделанные в любом контексте со ссылкой, будут влиять на данные, прочитанные в любом контексте с помощью ссылки.
Это не общая архитектура, и существует единственный способ существования. Те, кто немного сообразителен, увидят, что здесь много копирования, и они будут задаваться вопросом, хорошо ли это. Достаточно много копий продолжается в динамическом режиме, это динамика динамического языка. pthreads реализуется на уровне объекта, потому что хороший контроль можно получить над одним объектом, но методы – код, который выполняет программист, – имеют другой контекст, свободный от блокировки и копий – область локального метода. Сфера объекта в случае объекта pthreads следует рассматривать как способ совместного использования данных между контекстами, то есть целью. Имея это в виду, вы можете применять методы, чтобы избежать блокировки хранилища объектов, если это необходимо, например, передавать локальные переменные области в другие методы в поточном объекте, а не копировать их из хранилища объектов после выполнения.
Большинство библиотек и расширений, доступных для PHP, представляют собой тонкие оболочки вокруг сторонних сторон, функциональность ядра PHP до определенной степени – это одно и то же. pthreads не является тонкой оболочкой вокруг Posix Threads; это API потоковой обработки на основе Posix Threads. Нет смысла в реализации Threads в PHP, который пользователи не понимают или не могут использовать. Нет никакой причины, чтобы человек, не знающий, что такое мьютекс, не должен использовать все, что у них есть, как с точки зрения навыков, так и ресурсов. Объект функционирует как объект, но где бы ни возникали два контекста, pthreads обеспечивает стабильность и безопасность.
Любой, кто работал в java, увидит сходство между объектом pthreads и потокованием в java, те же люди не сомневаются в ошибке ConcurrentModificationException – поскольку это звучит ошибка, вызванная временем выполнения java, если два потока записывают одни и те же физические данные одновременно. Я понимаю, почему он существует, но это меня озадачивает тем, что с такими же дешевыми ресурсами, как и они, в сочетании с тем фактом, что среда выполнения может обнаруживать параллелизм в точное и единственное время, когда безопасность может быть достигнута для пользователя, что он выбирает бросить возможную фатальную ошибку во время выполнения, а не управлять выполнением и доступом к данным.
Никакие такие глупые ошибки не будут испущены pthreads, API написан, чтобы сделать threading стабильным и совместимым, насколько это возможно, я считаю.
Многопоточность не похожа на использование новой базы данных, пристальное внимание следует уделять каждому слову в руководстве и примерам, поставляемым с pthreads.
Наконец, из руководства PHP:
pthreads был и есть эксперимент с довольно хорошими результатами. Любое из его ограничений или возможностей может измениться в любое время; это характер экспериментов. Это недостатки – часто навязываемые реализацией – существуют по уважительной причине; цель pthreads – предоставить полезное решение для многозадачности в PHP на любом уровне. В среде, выполняемой pthreads, необходимы некоторые ограничения и ограничения, чтобы обеспечить стабильную среду.
Вот пример того, что Вилко предложил:
$cmd = 'nohup nice -n 10 /usr/bin/php -c /path/to/php.ini -f /path/to/php/file.php action=generate var1_id=23 var2_id=35 gen_id=535 > /path/to/log/file.log & echo $!'; $pid = shell_exec($cmd);
В основном это выполняет PHP-скрипт в командной строке, но сразу возвращает PID, а затем запускается в фоновом режиме. (Echo $! Гарантирует, что ничего другого не будет возвращено, кроме PID.) Это позволяет вашему скрипту PHP продолжить или выйти, если хотите. Когда я использовал это, я перенаправил пользователя на другую страницу, где каждые 5-60 секунд вызывается вызов AJAX, чтобы проверить, все ли работает отчет. (У меня есть таблица для хранения gen_id и пользователя, с которым она связана.) Скрипт проверки запускает следующее:
exec('ps ' . $pid , $processState); if (count($processState) < 2) { // less than 2 rows in the ps, therefore report is complete }
В этой технике есть короткая статья : http://nsaunders.wordpress.com/2007/01/12/running-a-background-process-in-php/
Короче: да, в php есть многопоточность, но вместо этого вы должны использовать многопроцессорность.
Всегда есть путаница в различии потоков и процессов, поэтому я кратко опишу оба:
Вы можете добиться параллельных вычислений, создав новые процессы (которые также содержат новый поток) с php. Если ваши потоки не требуют большой связи или синхронизации, это ваш выбор, поскольку процессы изолированы и не могут мешать работе друг друга. Даже если кто-то падает, это не касается других. Если вам нужно много общения, вы должны прочитать «многопоточность» или – к сожалению – подумайте об использовании другого языка программирования, потому что межпроцессное общение и синхронизация создают много цвета лица.
В php у вас есть два способа создать новый процесс:
пусть ОС сделает это за вас : вы можете сообщить своей операционной системе о создании нового процесса и запустить в нем новый (или тот же) PHP-скрипт.
для linux вы можете использовать следующее или рассмотреть ответ Дэррила Хейна :
$cmd = 'nice php script.php 2>&1 & echo $!'; pclose(popen($cmd, 'r'));
для окон вы можете использовать это:
$cmd = 'start "processname" /MIN /belownormal cmd /c "script.php 2>&1"'; pclose(popen($cmd, 'r'));
сделайте это самостоятельно с помощью fork : php также дает возможность использовать forking через функцию pcntl_fork () . Хороший учебник о том, как это сделать, можно найти здесь, но я настоятельно рекомендую не использовать его, поскольку fork является преступлением против человечества и особенно против oop.
Благодаря многопоточности все ваши потоки делятся своими ресурсами, поэтому вы можете легко общаться между ними и синхронизировать их без большого количества накладных расходов. С другой стороны, вы должны знать, что вы делаете, поскольку условия гонки и тупики легко производить, но очень сложно отлаживать.
Стандартный php не предоставляет многопоточности, но есть (экспериментальное) расширение, которое на самом деле делает – pthreads . Его документация api даже сделала его в php.net . С его помощью вы можете сделать некоторые вещи, как вы можете, на реальных языках программирования 🙂 вот так:
class MyThread extends Thread { public function run(){ //do something time consuming } } $t = new MyThread(); if($t->start()){ while($t->isRunning()){ echo "."; usleep(100); } $t->join(); }
вclass MyThread extends Thread { public function run(){ //do something time consuming } } $t = new MyThread(); if($t->start()){ while($t->isRunning()){ echo "."; usleep(100); } $t->join(); }
Для linux есть руководство по установке прямо здесь, в stackoverflow.
Для окон есть один сейчас:
Измените [phpDirectory] /php.ini и вставьте следующую строку
extension=php_pthreads.dll
Протестируйте его со сценарием выше с некоторым сном или что-то там, где есть комментарий.
И теперь большое НО : Хотя это действительно работает, php изначально не был создан для многопоточности. Существует поточно-безопасная версия php, а с v5.4 она кажется почти безнадежной, но использование php в многопоточной среде по-прежнему не рекомендуется в руководстве по php (но, возможно, они просто не обновили свое руководство по это, пока). Гораздо большая проблема может заключаться в том, что многие распространенные расширения не являются потокобезопасными . Таким образом, вы можете получить потоки с этим расширением php, но функции, в которых вы находитесь, по-прежнему не являются потокобезопасными, поэтому вы, вероятно, столкнетесь с условиями гонки, взаимоблокировками и т. Д. В коде, который вы не пишете …
Вы можете использовать pcntl_fork () для достижения чего-то подобного потокам. Технически это отдельные процессы, поэтому общение между ними не так просто с потоками, и я считаю, что это не сработает, если PHP вызывается apache.
Если кто-то заботится, я возродил php_threading (не то же самое, что и потоки, но похоже), и я действительно имею его до такой степени, что он работает (несколько) хорошо!
Страница проекта
Загрузить (для Windows PHP 5.3 VC9 TS)
Примеры
ПРОЧТИ МЕНЯ
pcntl_fork()
– это то, что вы ищете, но его процесс не работает на потоке. поэтому у вас возникнет проблема обмена данными. для их решения вы можете использовать функции семафора php ( http://www.php.net/manual/de/ref.sem.php ) очереди сообщений могут быть немного проще для начала, чем сегменты разделяемой памяти.
В любом случае, стратегия, которую я использую в веб-среде, которую я разрабатываю, которая загружает ресурсоемкие блоки веб-страницы (возможно, с внешними запросами) параллельно: я делаю очередь заданий, чтобы узнать, какие данные я жду, а затем я вилка от рабочих мест для каждого процесса. после их хранения они хранят свои данные в кэше apc под уникальным ключом, к которому может обращаться родительский процесс. после того, как все данные будут продолжены. Я использую простой usleep()
чтобы ждать, потому что связь между процессами невозможна в apache (дети потеряют связь со своими родителями и станут зомби …). поэтому это подводит меня к последнему: его важно убить каждого ребенка! есть также классы, которые обрабатывают процессы fork, но сохраняют данные, я не рассматривал их, но у zend framework есть один, и они обычно делают медленный, но надежный код. вы можете найти его здесь: http://zendframework.com/manual/1.9/en/zendx.console.process.unix.overview.html Я думаю, что они используют сегменты shm! но последнее, но не менее важное, есть ошибка на этом сайте zend, небольшая ошибка в примере.
while ($process1->isRunning() && $process2->isRunning()) { sleep(1); } should of course be: while ($process1->isRunning() || $process2->isRunning()) { sleep(1); }
Существует расширение Threading, созданное на основе PThreads, которое выглядит очень перспективным на https://github.com/krakjoe/pthreads
Просто обновление, похоже, что парни PHP работают над поддержкой потока и его доступными сейчас.
Вот ссылка на него: http://php.net/manual/en/book.pthreads.php
У меня есть класс потоковой передачи PHP, который работает безупречно в производственной среде уже более двух лет.
EDIT: Это теперь доступно как библиотека композитора и как часть моей MVC-структуры, Hazaar MVC.
Я знаю, что это старый вопрос, но вы можете посмотреть http://phpthreadlib.sourceforge.net/
Двунаправленная связь, поддержка Win32 и отсутствие необходимых расширений.
Вы когда-нибудь слышали о appserver
от techdivision?
Он написан на php и работает как сервер приложений, управляющий многопоточными приложениями для приложений с высоким трафиком. Является все еще в бета-версии, но очень интересной.
Существует довольно неясная и скоро устаревшая функция, называемая тиками . Единственное, что я когда-либо использовал для этого, это позволить сценарию захватить SIGKILL (Ctrl + C) и закрыть изящно.