#php #multithreading
#php #многопоточность
Вопрос:
Я тестирую интересную концепцию «многопоточности» в PHP. По сути, я работаю над тем, чтобы родительский процесс порождал дочерние процессы, которые выполняли бы что-то и возвращали результаты обратно родительскому процессу через стандартный вывод в виде обратного вызова.
То, как это происходит в моем примере, внутренний цикл слишком плотный и сжигает 99% процессора:
while(true){
$ret = $thread->Listen();
if( $ret == 'DOINGSTUFF' ){
break;
}
}
Я бы хотел уменьшить этот цикл while до зацикливания каждые 5 секунд, используя, например, sleep()
. Это выводит загрузку процессора на гораздо более рациональный уровень; однако я обеспокоен тем, что тогда «пропустит» некоторые дочерние «потоки», возвращающие результаты в случае, если один дочерний процесс завершится во время родительского спящего процесса.
Может ли эксперт по PHP сказать мне, обоснована ли эта проблема, и если да, могу ли я что-нибудь сделать, чтобы справиться?
Ответ №1:
В вашем примере используется proc_open
, что не совсем многопоточно. В любом случае, при использовании proc_open
потоки каналов будут доступны до тех пор, пока proc_close
не будет вызван, даже если процесс фактически завершен:
$proc = proc_open('which ls', $descriptorspec, $pipes);
sleep(5);
echo stream_get_contents($pipes[1]); // output '/bin/ls'
$proc = proc_open('which ls', $descriptorspec, $pipes);
sleep(5);
proc_close($proc);
echo stream_get_contents($pipes[1]); // E_WARNING: $pipes[1] not a valid stream
Также нет необходимости использовать sleep
. Обычно вы не хотите, чтобы скрипт зависал на 5 секунд каждый проход, ничего не делая. Вместо этого используйте usleep, что также снизит загрузку процессора, но все равно сделает скрипт отзывчивым:
while (true) {
// do stuff
usleep(50);
}
Вышеупомянутый режим будет находиться в режиме ожидания в течение 50 микросекунд, оставляя циклы процессора другим запущенным процессам.
Что касается чистой многопоточности, то в PHP это невозможно. Все, что вы можете сделать, это разветвить процесс. Разница с фактическим разветвлением и используемым вами методом ( proc_open
) заключается в том, что данные родительского процесса (переменные и т.д.) Также разветвляются на дочерний процесс. Разветвление следует использовать не в веб-приложениях, а только в программах командной строки, поскольку веб-серверы не очень хорошо его поддерживают.
Ответ №2:
Ну, как вы уже заметили, while (true) — это тот, который сжигает процессор, и вы не можете «замедлить» это. Вы хотите, чтобы ваше приложение вело себя как слушатель, скажем, сокет — оно активно только тогда, когда что-то хочет с ним поговорить, в противном случае оно просто остается бездействующим и «слушает». Вам действительно следует создать прослушиватель на одном из портов и повторно попробовать ваш пример, эмуляция прослушивателя приведет только к потере циклов процессора без причины. Это также упрощает взаимодействие между процессами, поскольку у вас есть сервер и подключенная к нему группа клиентов (процессов), так что вы можете обмениваться ресурсами любым удобным вам способом.
Кроме того, re: многопоточность в PHP — все, что вы можете сделать, это разветвить процесс, который на самом деле не является многопоточным и является бременем для ОС. Если вы действительно не хотите что-то делать параллельно, вам следует избегать разветвления любой ценой.