Estou usando pthreads para criar vários threads. Cada um desses threads em um ponto tenta usar da get_posts()
seguinte maneira:
$args = array(
'post_type' => 'post',
'post_status' => 'any'
);
$posts_list = get_posts($args);
No entanto, acabo com a seguinte falha:
HP Fatal error: Call to a member function get() on a non-object in C:\dev\wordpress\wp-includes\cache.php on line 123
Observe que, quando faço a mesma get_posts()
chamada em uma seção de código que não é encadeada, não tenho a falha.
Agora, minha pergunta, como chamar get_posts()
de dentro de um thread pthread ? E se eu não posso fazer isso, qual é a alternativa?
Obrigado.
Atualizar
Aqui está o código de exemplo
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()
chamada em uma seção de código que não é encadeada, não tenho a falha "; portanto, não há problema com minhaget_posts($args)
ligação. Além disso, não há código que precise ser protegido neste momento, estou apenas lendo no banco de dados do WordPress viaget_posts($args)
.Respostas:
Como existem muitos votos positivos para a pergunta, embora os problemas de multithreading sejam muito amplos para o formato de uma resposta, tentarei explicar por que você não deve usar a API do wordpress de maneira multithread.
Não se supõe que TL; DR - PHP esteja pronto para multithreading, o problema não é o próprio PHP, mas principalmente as bibliotecas que ele usa. É por isso que é recomendável não usar o modo de execução multithread no apache, embora em teoria deva ser um pouco mais rápido. Para aumentar o problema de a camada subjacente não estar pronta para multithread, o wordpress core viola o requisito mais básico de multithread - sem acesso livre aos globais.
Qual é o problema com globals em um ambiente multithread? vamos assumir que temos o código de aparência ingênua
Embora seja apenas um liner, não é uma operação atômica para a CPU, e são necessárias várias instruções no nível da máquina para executá-la actoalmente. Algo como
Agora vamos supor que temos dois threads AB que chamam
inc()
ao mesmo tempo (obviamente, com apenas uma CPU não existe o mesmo tempo) e que o valor inicial de $ g é 0, qual seria o valor de $ g depois que os dois threads terminaram? Depende de como o sistema operacional lida com multithreading, quando ele alterna entre threads. Nos sistemas operacionais de estilo "mais antigo", era o trabalho do encadeamento declarar, chamando uma API que o controle pode ser retirado, mas isso leva a muitos problemas com processos de mau comportamento que bloqueiam o sistema no sistema "moderno" que o sistema operacional utiliza. controlar sempre que lhe apetecer. Na vida real, o resultado do código será que $ g terá o valor 2, mas também existe a seguinte possibilidadeNo contexto de A
O resultado final é que $ g tem o valor de 1.
Obviamente, os globais não são o único problema e o manuseio de entradas e saídas também é essencial para problemas de leitura mútua.
No código multithreading adequado, você usa lock / mutex / semáforo / pipe / soquete .... para serializar o acesso a esses recursos globais para garantir que haverá um resultado previsível para a operação. Wordpress não faz isso.
Inferno, o wordpress não é seguro para vários processos. Na maioria das vezes, ele se livra disso porque o esquema do banco de dados é construído de uma maneira que, na vida real, impede a necessidade de modificar os mesmos dados de diferentes processos (postagens diferentes têm linhas diferentes e não compartilham dados), mas observe o código da barra lateral / widgets e tente imaginar o que acontecerá se dois administradores tentarem adicionar um widget diferente exatamente ao mesmo tempo. Como isso exigirá a manipulação de uma opção específica, o resultado final pode ser um dos dois widgets adicionados ou apenas um deles.
Voltar para multithrading. No unix, diferentemente do Windows, o custo adicional de gerar um processo em vez de encadear é insignificante, portanto, usar
wp_remote_get
com algum URL especial para chamar "encadeamento" adicional é uma coisa muito legítima a ser feita e evitar quase todas as armadilhas associadas ao multithreading.fonte