Я нашел этот пакет PECL под названием thread , но его пока нет. И на сайте PHP ничего не появляется.
Я нашел этот пакет PECL под названием thread , но его пока нет. И на сайте PHP ничего не появляется.
Ответы:
Мне ничего не известно. Следующим лучшим вариантом было бы просто заставить один скрипт выполнять другой через CLI, но это немного элементарно. В зависимости от того, что вы пытаетесь сделать и насколько это сложно, это может быть или не быть вариантом.
Из руководства PHP для расширения pthreads :
pthreads - это объектно-ориентированный API, который обеспечивает многопоточность на уровне пользователя в PHP. Он включает в себя все инструменты, необходимые для создания многопоточных приложений, ориентированных на Интернет или консоль. Приложения PHP могут создавать, читать, писать, выполнять и синхронизировать с потоками, рабочими процессами и стеками.
Как бы невероятно это ни звучало, это чистая правда. Сегодня 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 (даже в Windows), то, что программист создает, являются реальными потоками выполнения, но для того, чтобы эти потоки были полезными, они должны знать о PHP - иметь возможность выполнять пользовательский код, совместно использовать переменные и предоставлять полезные средства связи. (синхронизация). Таким образом, каждый поток создается с помощью экземпляра интерпретатора, но по замыслу его интерпретатор изолирован от всех других экземпляров интерпретатора - точно так же, как среды многопоточного серверного API. pthreads пытается восполнить пробел разумным и безопасным способом. Многие из проблем программиста потоков на C просто не существуют для программиста pthreads, по замыслу pthreads копируется при чтении и копируется при записи (ОЗУ дешево), поэтому никакие два экземпляра никогда не манипулируют одними и теми же физическими данными. , но оба они могут влиять на данные в другом потоке.
Зачем копировать при чтении и копировать при записи:
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 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. Нет смысла реализовывать потоки в PHP, которые пользователи не понимают или не могут использовать. Нет причин, по которым человек, не знающий, что такое мьютекс или что он делает, не должен иметь возможность использовать все, что у него есть, как с точки зрения навыков, так и с точки зрения ресурсов. Объект функционирует как объект, но там, где иначе столкнутся два контекста, pthreads обеспечивает стабильность и безопасность.
Любой, кто работал с java, увидит сходство между объектом pthreads и потоком в java, те же самые люди, без сомнения, увидят ошибку под названием ConcurrentModificationException - поскольку это звучит как ошибка, вызванная средой выполнения java, если два потока записывают одни и те же физические данные одновременно. Я понимаю, почему он существует, но меня сбивает с толку то, что с такими дешевыми ресурсами, в сочетании с тем фактом, что среда выполнения может обнаруживать параллелизм в точное и единственное время, когда безопасность может быть достигнута для пользователя, который он выбирает для генерировать возможно фатальную ошибку во время выполнения, а не управлять выполнением и доступом к данным.
Я полагаю, что pthreads не будет генерировать такие глупые ошибки, API написан для того, чтобы сделать потоки как можно более стабильными и совместимыми.
Многопоточность не похожа на использование новой базы данных, особое внимание следует уделять каждому слову в руководстве и примерам, поставляемым с 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'));
сделайте это самостоятельно с помощью вилки : php также предоставляет возможность использовать вилку с помощью функции pcntl_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();
}
Для Linux есть руководство по установке прямо здесь, на stackoverflow's.
Для окон теперь есть один:
Отредактируйте [phpDirectory] /php.ini и вставьте следующую строку
extension=php_pthreads.dll
Проверьте это с помощью приведенного выше сценария, немного поспав или что-то еще прямо там, где есть комментарий.
А теперь большое НО : хотя это действительно работает, php изначально не был предназначен для многопоточности. Существует поточно-ориентированная версия php, и с v5.4 она кажется почти безошибочной, но использование php в многопоточной среде все еще не рекомендуется в руководстве по php (но, возможно, они просто не обновили свое руководство по это, пока). Гораздо более серьезная проблема может заключаться в том, что многие распространенные расширения не являются потокобезопасными . Таким образом, вы можете получать потоки с этим расширением php, но функции, от которых вы зависите, по-прежнему не являются потокобезопасными, поэтому вы, вероятно, столкнетесь с условиями гонки, взаимоблокировками и т. Д. В коде, который вы не писали сами ...
Вы можете использовать pcntl_fork () для достижения чего-то похожего на потоки. Технически это отдельные процессы, поэтому связь между ними не так проста с потоками, и я считаю, что это не будет работать, если PHP будет вызван apache.
Если кому-то интересно , я возродил php_threading (не такой, как потоки, но похожий), и у меня он действительно есть до такой степени, что он работает (отчасти) хорошо!
pcntl_fork()
это то, что вы ищете, но его процесс разветвляется, а не распределяется. так что у вас возникнет проблема обмена данными. для их решения вы можете использовать семафорные функции phps ( http://www.php.net/manual/de/ref.sem.php ), очереди сообщений могут быть немного проще для начала, чем сегменты разделяемой памяти.
В любом случае, стратегия, которую я использую в разрабатываемой мной веб-структуре, которая загружает ресурсоемкие блоки веб-страницы (возможно, с внешними запросами) параллельно: я делаю очередь заданий, чтобы узнать, какие данные я жду, а затем я разветвляю от рабочих мест для каждого процесса. после этого они сохраняют свои данные в кэше apc под уникальным ключом, к которому родительский процесс может получить доступ. как только все данные будут там, это продолжается. Я использую простое usleep()
ожидание, потому что межпроцессное взаимодействие невозможно в apache (дети теряют связь со своими родителями и становятся зомби ...). Итак, это подводит меня к последнему: важно убить каждого ребенка самостоятельно! Есть также классы, которые обрабатывают форк, но хранят данные, я не проверял их, но у 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);
}
На основе PThreads активно разрабатывается расширение Threading, которое выглядит очень многообещающим по адресу https://github.com/krakjoe/pthreads.
Просто обновление, похоже, что ребята из PHP работают над поддержкой потока, и теперь он доступен.
Вот ссылка на него: http://php.net/manual/en/book.pthreads.php
У меня есть класс потоковой передачи PHP, который безупречно работает в производственной среде уже более двух лет.
РЕДАКТИРОВАТЬ: теперь это доступно как библиотека композитора и как часть моей инфраструктуры MVC, Hazaar MVC.
Я знаю, что это старый вопрос, но вы можете посмотреть http://phpthreadlib.sourceforge.net/
Двунаправленная связь, поддержка Win32 и никаких расширений.
Вы когда-нибудь слышали об этом appserver
от Techdivision?
Он написан на php и работает как сервер приложений, управляющий многопоточностью для приложений php с высоким трафиком. Все еще находится в стадии бета-тестирования, но очень продвигается.
Есть довольно малоизвестная и скоро будет устаревшая функция под названием тики . Единственное, для чего я когда-либо его использовал, - это позволить скрипту захватить SIGKILL (Ctrl + C) и изящно завершить работу.
pcntl_fork()
) работать при вызове из Apache?