Я использую pthreads для создания нескольких потоков. Каждый из этих потоков в какой-то момент пытается использовать get_posts()
следующее:
$args = array(
'post_type' => 'post',
'post_status' => 'any'
);
$posts_list = get_posts($args);
Однако я получаю следующее падение:
HP Fatal error: Call to a member function get() on a non-object in C:\dev\wordpress\wp-includes\cache.php on line 123
ПОЖАЛУЙСТА, ОБРАТИТЕ ВНИМАНИЕ, когда я делаю тот же get_posts()
вызов в разделе кода, который не является многопоточным, у меня нет сбоя.
Теперь мой вопрос, как позвонить get_posts()
из нити pthread ? И если я не могу этого сделать, какова альтернатива?
Спасибо.
Обновить
Вот пример кода
class My_Thread extends Thread {
public function run() {
/* DO SOME STUFF HERE */
$args = array(
'post_type' => 'post',
'post_status' => 'any'
);
$posts_list = get_posts($args); // <------ This is causing the crash
}
}
// Create a array
$threads = array();
//Iniciate Miltiple Thread
foreach ( range("A", "C") as $i ) {
$threads[] = new My_Thread($i);
}
// Start The Threads
foreach ($threads as $thread) {
$thread->start();
}
get_posts()
вызов в секции кода, которая не является многопоточной, у меня не происходит сбой »; так что это не проблема с моимget_posts($args)
звонком. Более того, на данный момент нет кода, который нужно защищать, я просто читаю из БД WordPress черезget_posts($args)
.Ответы:
Поскольку существует множество возражений на этот вопрос, хотя проблемы многопоточности слишком широки для формата ответа, я попытаюсь объяснить, почему не следует использовать WordPress API многопоточным способом ....
TL; DR - PHP не считается готовым к многопоточности, проблема не в самом PHP, а в основном в используемых им библиотеках. Вот почему рекомендуется не использовать многопоточный режим выполнения в Apache, хотя теоретически он должен быть несколько быстрее. Чтобы добавить к проблеме того, что нижележащий слой не готов к многопоточности, ядро WordPress нарушает самое основное требование многопоточности - свободный доступ к глобальным переменным.
В чем проблема глобалов в многопоточной среде? давайте предположим, что у нас есть наивно выглядящий код
Хотя это всего лишь одна строка, это не атомарная операция для ЦП, и для ее фактического выполнения требуется несколько инструкций на уровне машины. Что-то вроде
Теперь давайте предположим, что у нас есть два потока AB, которые вызывают
inc()
«в одно и то же время» (очевидно, что только с одним ЦП нет такого понятия, как одно и то же время), и что начальное значение $ g равно 0, что будет значением $ г после окончания обоих потоков? Это будет зависеть от того, как ОС обрабатывает многопоточность, когда она переключается между потоками. В «старых» ОС стиль работы потока заключался в том, чтобы объявить, вызвав API, от которого можно получить контроль, но это приводит ко многим проблемам с процессами с плохим поведением, блокирующими систему для этого в «современных» ОС, которые использует ОС. контроль, когда это кажется В реальной жизни результатом кода будет то, что $ g будет иметь значение 2, но есть также следующая возможностьВ контексте А
Конечным результатом является то, что $ g имеет значение 1.
Очевидно, глобальные переменные - не единственная проблема, и обработка входных и выходных данных также является ядром для многопоточности.
В правильном многопоточном коде вы используете lock / mutex / semaphore / pipe / socket ...., чтобы сериализовать доступ к таким глобальным ресурсам, чтобы обеспечить предсказуемый результат операции. Wordpress не делает этого.
Черт, WordPress не является даже безопасным для многих процессов. Большую часть времени это обходится без него, потому что схема БД построена таким образом, что в реальной жизни предотвращает необходимость изменять одни и те же данные из разных процессов (разные записи имеют разные строки и не разделяют данные), но посмотрите на код боковой панели / виджетов и попытайтесь представить, что произойдет, если два администратора попытаются добавить другой виджет в одно и то же время. Поскольку это потребует манипулирования одним конкретным параметром, конечным результатом может быть добавление обоих виджетов или только одного из них.
Вернуться к мультитрейдингу. В Unix, в отличие от Windows, дополнительные затраты на создание процесса вместо потока незначительны, поэтому использование
wp_remote_get
с каким-то специальным URL для вызова дополнительного «потока» является вполне допустимым и позволяет избежать почти всех ловушек, связанных с многопоточностью.источник