Поскольку существует множество возражений на этот вопрос, хотя проблемы многопоточности слишком широки для формата ответа, я попытаюсь объяснить, почему не следует использовать WordPress API многопоточным способом ....
TL; DR - PHP не считается готовым к многопоточности, проблема не в самом PHP, а в основном в используемых им библиотеках. Вот почему рекомендуется не использовать многопоточный режим выполнения в Apache, хотя теоретически он должен быть несколько быстрее. Чтобы добавить к проблеме того, что нижележащий слой не готов к многопоточности, ядро WordPress нарушает самое основное требование многопоточности - свободный доступ к глобальным переменным.
В чем проблема глобалов в многопоточной среде? давайте предположим, что у нас есть наивно выглядящий код
function inc() {
global $g;
$g++;
}
Хотя это всего лишь одна строка, это не атомарная операция для ЦП, и для ее фактического выполнения требуется несколько инструкций на уровне машины. Что-то вроде
move $g to register D
increment register D
move register D to $g
Теперь давайте предположим, что у нас есть два потока AB, которые вызывают inc()
«в одно и то же время» (очевидно, что только с одним ЦП нет такого понятия, как одно и то же время), и что начальное значение $ g равно 0, что будет значением $ г после окончания обоих потоков? Это будет зависеть от того, как ОС обрабатывает многопоточность, когда она переключается между потоками. В «старых» ОС стиль работы потока заключался в том, чтобы объявить, вызвав API, от которого можно получить контроль, но это приводит ко многим проблемам с процессами с плохим поведением, блокирующими систему для этого в «современных» ОС, которые использует ОС. контроль, когда это кажется В реальной жизни результатом кода будет то, что $ g будет иметь значение 2, но есть также следующая возможность
В контексте А
move $g to register D
// value of D is 0
// OS stores the content of registers and switches to thread B
// B increments $g to 1 and finishes working
// OS restores content of registers to the context of thread A
// Value of register D is now 0
increment register D
move register D to $g
Конечным результатом является то, что $ g имеет значение 1.
Очевидно, глобальные переменные - не единственная проблема, и обработка входных и выходных данных также является ядром для многопоточности.
В правильном многопоточном коде вы используете lock / mutex / semaphore / pipe / socket ...., чтобы сериализовать доступ к таким глобальным ресурсам, чтобы обеспечить предсказуемый результат операции. Wordpress не делает этого.
Черт, WordPress не является даже безопасным для многих процессов. Большую часть времени это обходится без него, потому что схема БД построена таким образом, что в реальной жизни предотвращает необходимость изменять одни и те же данные из разных процессов (разные записи имеют разные строки и не разделяют данные), но посмотрите на код боковой панели / виджетов и попытайтесь представить, что произойдет, если два администратора попытаются добавить другой виджет в одно и то же время. Поскольку это потребует манипулирования одним конкретным параметром, конечным результатом может быть добавление обоих виджетов или только одного из них.
Вернуться к мультитрейдингу. В Unix, в отличие от Windows, дополнительные затраты на создание процесса вместо потока незначительны, поэтому использование wp_remote_get
с каким-то специальным URL для вызова дополнительного «потока» является вполне допустимым и позволяет избежать почти всех ловушек, связанных с многопоточностью.