Альтернатива get_posts () из-за краха кеша многопоточности

Я использую 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() в разделе кода, который не является резьбовым, I не имеют сбоя.

Теперь, мой вопрос, как вызвать get_posts() из потока pthread ? И если я не могу этого сделать, какова альтернатива?

Спасибо.


Update

Вот пример кода

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();
}
7 голосов | спросил Greeso 24 ThuEurope/Moscow2015-12-24T08:22:04+03:00Europe/Moscow12bEurope/MoscowThu, 24 Dec 2015 08:22:04 +0300 2015, 08:22:04

1 ответ


3

Так как на вопрос много вопросов, хотя проблемы многопоточности слишком широки для формата ответа, я попытаюсь объяснить, почему вы не должны использовать Wordpress API многопоточным способом ....

TL; DR - PHP не считается многопоточным, проблема заключается не в самом PHP, а в основном в библиотеках, которые он использует. Поэтому рекомендуется не использовать многопоточный режим выполнения в apache, хотя теоретически он должен быть несколько быстрее. Чтобы добавить к тому, что базовый уровень не является многопоточным, ядро ​​wordpress нарушает самое основное требование многопоточности - нет свободного доступа к глобальным переменным.

В чем проблема с глобальными переменными в многопоточной среде? давайте предположим, что у нас наивный код

function inc() {
  global $g;

  $g++;
}

В то время как это всего лишь один лайнер, это не атомная операция для CPU, и требуется несколько инструкций на уровне машины, чтобы выполнить его. Что-то вроде

move $g to register D
increment register D
move register D to $g

Теперь предположим, что у нас есть два потока AB, которые вызывают inc() в то же время (очевидно, только с одним процессором нет такая вещь как то же время), и что начальное значение $ g равно 0, каково будет значение $ g после завершения обоих потоков? Это будет зависеть от того, как ОС обрабатывает многопоточность, когда она переключается между потоками. В «устаревшем» стилевом стиле задача объявления была объявлена, вызвав API, который может быть взят из него, но это приводит к множеству проблем с плохой работой, блокирующей систему для «современной» ОС, которую принимает ОС когда когда-либо это кажется. В реальной жизни результатом кода будет то, что $ g будет иметь значение 2, но есть также следующая возможность

В контексте A

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.

Очевидно, что глобальные переменные - это не единственная проблема, и обработка входов и выходов также является ядром для проблем mutithreading.

В правильном многопоточном коде вы используете lock /mutex /semaphore /pipe /socket .... для сериализации доступа к таким глобальным ресурсам, чтобы убедиться, что операция будет предсказуемой. Wordpress этого не делает.

Черт, WordPress даже не безопасен для многих процессов. Большую часть времени он уходит от него, потому что схема БД построена таким образом, что при использовании в реальной жизни предотвращает необходимость изменения одних и тех же данных из разных процессов (разные записи имеют разные строки и не делят данные), но посмотрите на код боковой панели /виджета и попытайтесь представить, что произойдет, если две админы попытаются добавить другой виджет точно в одно и то же время. Поскольку для этого потребуется манипулирование одной конкретной опцией, конечным результатом может быть либо добавленный виджетов, либо только один из них.

Вернемся к мультитрейдингу. В unix, в отличие от окон, дополнительная стоимость нереста процесса вместо потока ничтожно мала, поэтому с помощью wp_remote_get с некоторым специальным url для вызова дополнительных «thread» - это очень законная вещь и избегать почти всех ловушек, связанных с многопотоком.

ответил Mark Kaplun 27 SunEurope/Moscow2015-12-27T08:42:40+03:00Europe/Moscow12bEurope/MoscowSun, 27 Dec 2015 08:42:40 +0300 2015, 08:42:40

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132