Encontrei este pacote PECL chamado threads , mas ainda não há um lançamento. E nada está chegando no site PHP.
Encontrei este pacote PECL chamado threads , mas ainda não há um lançamento. E nada está chegando no site PHP.
Respostas:
Não há nada disponível que eu saiba. A próxima melhor coisa seria simplesmente fazer com que um script execute outro via CLI, mas isso é um pouco rudimentar. Dependendo do que você está tentando fazer e da complexidade, isso pode ou não ser uma opção.
No manual do PHP para a extensão pthreads :
O pthreads é uma API orientada a objetos que permite multi-threading para usuários no PHP. Ele inclui todas as ferramentas necessárias para criar aplicativos multithread direcionados à Web ou ao console. Os aplicativos PHP podem criar, ler, escrever, executar e sincronizar com Threads, Workers e Stackables.
Por incrível que pareça, é totalmente verdade. Hoje, o PHP pode multiencadear para aqueles que desejam experimentá-lo.
Na primeira versão do PHP4, em 22 de maio de 2000, o PHP foi enviado com uma arquitetura segura de encadeamento - uma maneira de executar várias instâncias de seu interpretador em encadeamentos separados em ambientes SAPI (API do servidor) com vários encadeamentos. Nos últimos 13 anos, o design dessa arquitetura foi mantido e avançado: desde então está em uso de produção nos maiores sites do mundo.
A segmentação na área de usuários nunca foi uma preocupação para a equipe do PHP e permanece como tal hoje. Você deve entender que, no mundo em que o PHP atua, já existe um método definido de dimensionamento - adicione hardware. Ao longo dos muitos anos em que o PHP existiu, o hardware ficou cada vez mais barato e, portanto, isso se tornou uma preocupação cada vez menor para a equipe do PHP. Enquanto estava ficando mais barato, também ficou muito mais poderoso; hoje, nossos telefones celulares e tablets possuem arquiteturas de núcleo duplo e quádruplo e muita memória RAM, nossos desktops e servidores geralmente têm 8 ou 16 núcleos, 16 e 32 gigabytes de RAM, embora nem sempre possamos ter dois dentro do orçamento e ter dois computadores raramente é útil para a maioria de nós.
Além disso, o PHP foi escrito para os não programadores, pois é um idioma nativo para muitos entusiastas. A razão pela qual o PHP é tão facilmente adotado é porque é uma linguagem fácil de aprender e escrever. A razão pela qual o PHP é tão confiável hoje em dia é por causa da grande quantidade de trabalho que é aplicada em seu design e de todas as decisões tomadas pelo grupo PHP. É a confiabilidade e a grandeza que a mantêm à vista, depois de todos esses anos; onde seus rivais caíram no tempo ou na pressão.
A programação multithread não é fácil para a maioria, mesmo com a API mais coerente e confiável, há coisas diferentes em que pensar e muitos conceitos errados. O grupo PHP não deseja que o multi-threading do usuário seja um recurso principal, nunca recebeu muita atenção - e com razão. PHP não deve ser complexo para todos.
Considerando tudo, ainda há benefícios em permitir que o PHP utilize os recursos prontos e testados para produção, para permitir um meio de tirar o máximo proveito do que temos, ao adicionar mais nem sempre é uma opção e por muito nunca é realmente necessário.
O pthreads alcança, para aqueles que desejam explorá-lo, uma API que permite ao usuário aplicativos PHP multiencadeados. Sua API é um trabalho em andamento e designou um nível beta de estabilidade e integridade.
É do conhecimento geral que algumas das bibliotecas que o PHP usa não são seguras para threads, deve ficar claro para o programador que os pthreads não podem mudar isso e não tentam tentar. No entanto, qualquer biblioteca que seja segura para threads é utilizável, como em qualquer outra configuração segura para threads do intérprete.
O pthreads utiliza Threads Posix (mesmo no Windows), o que o programador cria são threads reais de execução, mas para que esses threads sejam úteis, eles devem estar cientes do PHP - capaz de executar código de usuário, compartilhar variáveis e permitir um meio útil de comunicação ( sincronização ). Portanto, todo encadeamento é criado com uma instância do intérprete, mas, por design, ele é isolado de todas as outras instâncias do intérprete - assim como os ambientes da API do servidor com vários encadeamentos. O pthreads tenta preencher a lacuna de maneira sã e segura. Muitas das preocupações do programador de encadeamentos em C simplesmente não existem para o programador de pthreads; por design, pthreads é cópia na leitura e cópia na gravação (a RAM é barata); portanto, duas instâncias nunca manipulam os mesmos dados físicos. , mas ambos podem afetar os dados em outro encadeamento.
Por que copiar na leitura e copiar na gravação:
public function run() {
...
(1) $this->data = $data;
...
(2) $this->other = someOperation($this->data);
...
}
(3) echo preg_match($pattern, $replace, $thread->data);
(1) Enquanto um bloqueio de leitura e gravação é mantido no armazenamento de dados do objeto pthreads, os dados são copiados do local original na memória para o armazenamento de objetos. O pthreads não ajusta o refcount da variável, o Zend pode liberar os dados originais se não houver mais referências a ele.
(2) O argumento para someOperation faz referência ao armazenamento de objetos, os dados originais armazenados, que são uma cópia do resultado de (1), são copiados novamente para o mecanismo em um contêiner zval, enquanto isso ocorre em um bloqueio de leitura. o armazenamento de objetos, a trava é liberada e o mecanismo pode executar a função. Quando o zval é criado, ele possui uma refcount de 0, permitindo que o mecanismo libere a cópia na conclusão da operação, porque não existem outras referências a ele.
(3) O último argumento para preg_match faz referência ao armazenamento de dados, um bloqueio de leitura é obtido, os dados configurados em (1) são copiados para um zval, novamente com um refcount de 0. O bloqueio é liberado. A chamada para preg_match opera em uma cópia dos dados, que é ela mesma uma cópia dos dados originais.
Coisas a saber:
A tabela de hash do armazenamento de objetos em que os dados são armazenados, com segurança para threads, é
baseada no TsHashTable enviado com PHP, pelo Zend.
O armazenamento de objetos tem um bloqueio de leitura e gravação, um bloqueio de acesso adicional é fornecido para o TsHashTable, de modo que, se requer (e exige var_dump / print_r, acesso direto às propriedades que o mecanismo PHP deseja referenciá-los), os pthreads podem manipular o TsHashTable fora da API definida.
Os bloqueios são mantidos apenas enquanto as operações de cópia ocorrem, quando as cópias foram feitas, os bloqueios são liberados, em uma ordem sensata.
Isso significa:
Quando ocorre uma gravação, não apenas um bloqueio de leitura e gravação é mantido, mas também um bloqueio de acesso adicional. A tabela em si está bloqueada, não há como outro contexto poder bloquear, ler, escrever ou afetá-la.
Quando ocorre uma leitura, não apenas o bloqueio de leitura é mantido, mas também o bloqueio de acesso adicional, novamente a tabela está bloqueada.
Dois contextos não podem acessar física nem simultaneamente os mesmos dados do armazenamento de objetos, mas as gravações feitas em qualquer contexto com uma referência afetarão os dados lidos em qualquer contexto com uma referência.
Isso não é arquitetura compartilhada e a única maneira de existir é coexistir. Aqueles que são um pouco mais experientes verão isso, há muitas cópias acontecendo aqui e se perguntam se isso é uma coisa boa. Muitas cópias são realizadas em um tempo de execução dinâmico, que é a dinâmica de uma linguagem dinâmica. O pthreads é implementado no nível do objeto, porque um bom controle pode ser obtido sobre um objeto, mas os métodos - o código que o programador executa - têm outro contexto, livre de bloqueios e cópias - o escopo do método local. O escopo do objeto no caso de um objeto pthreads deve ser tratado como uma maneira de compartilhar dados entre contextos, e é esse o objetivo. Com isso em mente, você pode adotar técnicas para evitar o bloqueio do armazenamento de objetos, a menos que seja necessário,
A maioria das bibliotecas e extensões disponíveis para PHP são invólucros finos em torno de terceiros; a principal funcionalidade do PHP é a mesma coisa. O pthreads não é um invólucro fino ao redor dos Posix Threads; é uma API de segmentação baseada em threads Posix. Não há sentido em implementar Threads no PHP que seus usuários não entendam ou não possam usar. Não há razão para que uma pessoa sem conhecimento do que é ou não um mutex não possa tirar proveito de tudo o que possui, tanto em termos de habilidade quanto de recursos. Um objeto funciona como um objeto, mas onde quer que dois contextos colidem, pthreads fornece estabilidade e segurança.
Qualquer pessoa que tenha trabalhado em java verá as semelhanças entre um objeto pthreads e o encadeamento em java, essas mesmas pessoas sem dúvida terão visto um erro chamado ConcurrentModificationException - pois soa um erro gerado pelo tempo de execução do java se dois threads gravam os mesmos dados físicos simultaneamente. Entendo por que ele existe, mas me deixa perplexo que, com recursos tão baratos quanto eles, juntamente com o fato de o tempo de execução ser capaz de detectar a simultaneidade no momento exato e único em que a segurança possa ser alcançada para o usuário, ele opte por gere um erro possivelmente fatal no tempo de execução, em vez de gerenciar a execução e o acesso aos dados.
Nenhum erro estúpido será emitido pelo pthreads; a API foi criada para tornar o encadeamento o mais estável e compatível possível, acredito.
Multi-threading não é como usar um novo banco de dados, deve-se prestar muita atenção a todas as palavras do manual e exemplos fornecidos com pthreads.
Por fim, no manual do PHP:
O pthreads foi e é um experimento com bons resultados. Qualquer uma de suas limitações ou recursos pode mudar a qualquer momento; essa é a natureza da experimentação. Suas limitações - geralmente impostas pela implementação - existem por um bom motivo; O objetivo do pthreads é fornecer uma solução utilizável para multitarefa em PHP em qualquer nível. No ambiente em que o pthreads é executado, são necessárias algumas restrições e limitações para fornecer um ambiente estável.
Aqui está um exemplo do que Wilco sugeriu:
$cmd = 'nohup nice -n 10 /usr/bin/php -c /path/to/php.ini -f /path/to/php/file.php action=generate var1_id=23 var2_id=35 gen_id=535 > /path/to/log/file.log & echo $!';
$pid = shell_exec($cmd);
Basicamente, isso executa o script PHP na linha de comando, mas retorna imediatamente o PID e depois é executado em segundo plano. (O eco $! Garante que nada mais seja retornado além do PID.) Isso permite que seu script PHP continue ou saia, se você desejar. Quando usei isso, redirecionei o usuário para outra página, onde a cada 5 a 60 segundos é feita uma chamada AJAX para verificar se o relatório ainda está em execução. (Eu tenho uma tabela para armazenar o gen_id e o usuário ao qual ele está relacionado.) O script de verificação executa o seguinte:
exec('ps ' . $pid , $processState);
if (count($processState) < 2) {
// less than 2 rows in the ps, therefore report is complete
}
Há um breve post sobre esta técnica aqui: http://nsaunders.wordpress.com/2007/01/12/running-a-background-process-in-php/
Resumindo: sim, há multithreading no php, mas você deve usar o multiprocessamento.
Sempre há um pouco de confusão sobre a distinção de threads e processos, então, em breve, descreverei os dois:
Você pode obter computação paralela criando novos processos (que também contêm um novo thread) com php. Se seus encadeamentos não precisarem de muita comunicação ou sincronização, a escolha é sua, pois os processos são isolados e não podem interferir no trabalho um do outro. Mesmo se um travar, isso não diz respeito aos outros. Se você precisar de muita comunicação, continue lendo em "multithreading" ou - infelizmente - considere usar outra linguagem de programação, porque a comunicação e a sincronização entre processos introduzem muita tez.
No php, você tem duas maneiras de criar um novo processo:
deixe o sistema operacional fazer isso por você : você pode dizer ao seu sistema operacional para criar um novo processo e executar um novo (ou o mesmo) script php nele.
para linux, você pode usar o seguinte ou considerar a resposta de Darryl Hein :
$cmd = 'nice php script.php 2>&1 & echo $!';
pclose(popen($cmd, 'r'));
para windows você pode usar isso:
$cmd = 'start "processname" /MIN /belownormal cmd /c "script.php 2>&1"';
pclose(popen($cmd, 'r'));
faça você mesmo com um fork : o php também oferece a possibilidade de usar bifurcação através da função pcntl_fork () . Um bom tutorial sobre como fazer isso pode ser encontrado aqui, mas eu recomendo fortemente não usá-lo, pois o fork é um crime contra a humanidade e especialmente contra oop.
Com o multithreading, todos os seus threads compartilham seus recursos para que você possa se comunicar facilmente e sincronizá-los sem muita sobrecarga. Por outro lado, você precisa saber o que está fazendo, pois as condições e os impasses da corrida são fáceis de produzir, mas muito difíceis de depurar.
O php padrão não fornece multithreading, mas existe uma extensão (experimental) que realmente fornece - pthreads . Sua documentação da API chegou ao php.net . Com ele, você pode fazer algumas coisas em linguagens de programação reais :-) assim:
class MyThread extends Thread {
public function run(){
//do something time consuming
}
}
$t = new MyThread();
if($t->start()){
while($t->isRunning()){
echo ".";
usleep(100);
}
$t->join();
}
Para linux, há um guia de instalação aqui no stackoverflow.
Para o Windows, existe um agora:
Edite [phpDirectory] /php.ini e insira a seguinte linha
extension=php_pthreads.dll
Teste-o com o script acima com um pouco de sono ou algo ali onde está o comentário.
E agora o grande MAS : Embora isso realmente funcione, o php não foi feito originalmente para multithreading. Existe uma versão segura do thread do php e, a partir da v5.4, parece estar praticamente livre de erros, mas o uso do php em um ambiente com vários threads ainda é desencorajado no manual do php (mas talvez eles não tenham atualizado o manual em isso ainda). Um problema muito maior pode ser o fato de muitas extensões comuns não serem seguras para threads . Portanto, você pode obter threads com esta extensão php, mas as funções das quais você depende ainda não são seguras, portanto você provavelmente encontrará condições de corrida, impasses e assim por diante no código que você não escreveu.
Você pode usar o pcntl_fork () para obter algo semelhante aos threads. Tecnicamente, são processos separados, portanto a comunicação entre os dois não é tão simples com threads, e acredito que não funcionará se o PHP for chamado pelo apache.
Se alguém se importa, eu revivi o php_threading (não o mesmo que o thread, mas semelhante) e na verdade o tenho ao ponto em que funciona (um pouco) bem!
pcntl_fork()
é o que você está procurando, mas seu processo não é bifurcado. então você terá o problema da troca de dados. Para resolvê-los, você pode usar as funções de semáforo phps ( http://www.php.net/manual/de/ref.sem.php ) as filas de mensagens podem ser um pouco mais fáceis para o início do que os segmentos de memória compartilhada.
De qualquer forma, uma estratégia que estou usando em uma estrutura da Web que estou desenvolvendo que carrega blocos intensivos em recursos de uma página da Web (provavelmente com solicitações externas) paralela: estou fazendo uma fila de tarefas para saber quais dados estou esperando e depois bifurco fora dos trabalhos para cada processo. uma vez feito, eles armazenam seus dados no cache apc sob uma chave única que o processo pai pode acessar. assim que todos os dados estiverem lá, eles continuam. Estou usando o simple usleep()
to wait porque a comunicação entre processos não é possível no apache (as crianças perdem a conexão com os pais e se tornam zumbis ...). então isso me leva à última coisa: é importante matar todas as crianças! há também classes que processam os processos, mas mantêm os dados, eu não os examinei, mas o zend framework possui um, e eles geralmente fazem um código lento, mas confiável. Você pode encontrá-lo aqui:
http://zendframework.com/manual/1.9/en/zendx.console.process.unix.overview.html
eu acho que eles usam segmentos shm! bem, por último mas não menos importante, há um erro neste site do zend, um pequeno erro no exemplo.
while ($process1->isRunning() && $process2->isRunning()) {
sleep(1);
}
should of course be:
while ($process1->isRunning() || $process2->isRunning()) {
sleep(1);
}
Há uma extensão Threading sendo ativamente desenvolvida com base no PThreads que parece muito promissora em https://github.com/krakjoe/pthreads
Apenas uma atualização, parece que o pessoal do PHP está trabalhando no segmento de suporte e está disponível agora.
Aqui está o link para ele: http://php.net/manual/en/book.pthreads.php
Eu tenho uma classe de encadeamento PHP que está funcionando perfeitamente em um ambiente de produção há mais de dois anos.
EDIT: Agora está disponível como uma biblioteca de compositores e como parte do meu framework MVC, o Hazaar MVC.
Eu sei que essa é uma pergunta antiga, mas você pode consultar http://phpthreadlib.sourceforge.net/
Comunicação bidirecional, suporte para Win32 e nenhuma extensão necessária.
Já ouviu falar appserver
de techdivision?
É escrito em php e funciona como um servidor de aplicativos gerenciando multithreads para aplicativos php de alto tráfego. Ainda está na versão beta, mas muito promissor.
Existe o recurso bastante obscuro, e que será preterido em breve, chamado ticks . A única coisa que eu já usei é permitir que um script capture SIGKILL (Ctrl + C) e feche normalmente.
pcntl_fork()
) funcionará se for chamado do Apache?