Ho trovato questo pacchetto PECL chiamato thread , ma non esiste ancora una versione. E non sta succedendo nulla sul sito Web di PHP.
Ho trovato questo pacchetto PECL chiamato thread , ma non esiste ancora una versione. E non sta succedendo nulla sul sito Web di PHP.
Risposte:
Non c'è nulla di cui io sia a conoscenza. La prossima cosa migliore sarebbe semplicemente far eseguire uno script a un altro tramite CLI, ma è un po 'rudimentale. A seconda di cosa stai cercando di fare e di quanto sia complesso, questa potrebbe essere o meno un'opzione.
Dal manuale di PHP per l' estensione pthreads :
pthreads è un'API orientata agli oggetti che consente il multi-threading user-land in PHP. Include tutti gli strumenti necessari per creare applicazioni multi-thread destinate al Web o alla console. Le applicazioni PHP possono creare, leggere, scrivere, eseguire e sincronizzare con Thread, Lavoratori e Stackable.
Per quanto incredibile possa sembrare, è del tutto vero. Oggi PHP può eseguire il multi-thread per coloro che desiderano provarlo.
La prima versione di PHP4, 22 maggio 2000, PHP è stata fornita con un'architettura thread-safe: un modo per eseguire più istanze del suo interprete in thread separati in ambienti SAPI (Server API) multi-thread. Negli ultimi 13 anni, il design di questa architettura è stato mantenuto e avanzato: da allora è in uso nella produzione sui più grandi siti Web del mondo.
Il thread nella terra degli utenti non è mai stato un problema per il team di PHP, e lo è ancora oggi. Dovresti capire che nel mondo in cui PHP fa affari, esiste già un metodo di ridimensionamento definito: aggiungere hardware. Nel corso degli anni PHP è esistito, l'hardware è diventato sempre più economico e quindi questo è diventato sempre più un problema per il team PHP. Mentre stava diventando più economico, divenne anche molto più potente; oggi, i nostri telefoni cellulari e tablet hanno architetture dual e quad core e molta RAM per andare con esso, i nostri desktop e server hanno comunemente 8 o 16 core, 16 e 32 gigabyte di RAM, anche se potremmo non essere sempre in grado di avere due nel rispetto del budget e avere due desktop raramente è utile per la maggior parte di noi.
Inoltre, PHP è stato scritto per i non programmatori, è la lingua madre di molti hobbisti. Il motivo per cui PHP è così facilmente adottato è perché è una lingua facile da imparare e scrivere. Il motivo per cui PHP è così affidabile oggi è a causa della grande quantità di lavoro che viene svolto nella sua progettazione e di ogni singola decisione presa dal gruppo PHP. La sua affidabilità e la sua straordinaria grandezza lo tengono sotto i riflettori, dopo tutti questi anni; dove i suoi rivali sono caduti nel tempo o nella pressione.
La programmazione multi-thread non è facile per la maggior parte, anche con l'API più coerente e affidabile, ci sono diverse cose a cui pensare e molte idee sbagliate. Il gruppo PHP non desidera che il multi-threading di terra dell'utente sia una caratteristica fondamentale, non gli è mai stata prestata molta attenzione, e giustamente. PHP non dovrebbe essere complesso, per tutti.
Tutto sommato, ci sono ancora vantaggi nel consentire a PHP di utilizzare le sue funzionalità pronte per la produzione e testate per consentire un modo per ottenere il massimo da ciò che abbiamo, quando aggiungere di più non è sempre un'opzione e per molto di compiti non è mai veramente necessario.
pthreads realizza, per coloro che desiderano esplorarlo, un'API che consente a un utente di utilizzare applicazioni PHP multi-thread. L'API è in fase di sviluppo e ha designato un livello beta di stabilità e completezza.
È risaputo che alcune delle librerie utilizzate da PHP non sono thread-safe, dovrebbe essere chiaro al programmatore che pthreads non può cambiarlo e non tenta di provare. Tuttavia, è possibile utilizzare qualsiasi libreria protetta da thread, come in qualsiasi altra configurazione dell'interprete thread-safe.
pthreads utilizza i thread Posix (anche in Windows), ciò che il programmatore crea sono veri e propri thread di esecuzione, ma affinché questi thread siano utili, devono essere consapevoli di PHP - in grado di eseguire codice utente, condividere variabili e consentire un utile mezzo di comunicazione (sincronizzazione). Quindi ogni thread viene creato con un'istanza dell'interprete, ma per impostazione predefinita, il suo interprete è isolato da tutte le altre istanze dell'interprete, proprio come gli ambienti API Server multi-thread. pthreads tenta di colmare il divario in modo sano e sicuro. Molte delle preoccupazioni del programmatore di thread in C non sono lì per il programmatore di pthreads, in base alla progettazione, pthreads è copia su lettura e copia su scrittura (la RAM è economica), quindi non ci sono mai due casi che manipolano gli stessi dati fisici , ma entrambi possono influire sui dati in un altro thread.
Perché copiare su lettura e copia su scrittura:
public function run() {
...
(1) $this->data = $data;
...
(2) $this->other = someOperation($this->data);
...
}
(3) echo preg_match($pattern, $replace, $thread->data);
(1) Mentre un blocco di lettura e scrittura sono conservati nell'archivio dati oggetto pthreads, i dati vengono copiati dalla loro posizione originale in memoria nell'archivio oggetti. pthreads non regola il refcount della variabile, Zend è in grado di liberare i dati originali se non ci sono ulteriori riferimenti ad esso.
(2) L'argomento di someOperation fa riferimento all'archivio oggetti, i dati originali memorizzati, che a sua volta una copia del risultato di (1), vengono nuovamente copiati per il motore in un contenitore zval, mentre in questo caso viene mantenuto un blocco di lettura l'archivio oggetti, il blocco viene rilasciato e il motore può eseguire la funzione. Quando viene creato zval, ha un nuovo conto di 0, che consente al motore di liberare la copia al completamento dell'operazione, perché non esistono altri riferimenti ad essa.
(3) L'ultimo argomento di preg_match fa riferimento all'archivio dati, si ottiene un blocco di lettura, il set di dati in (1) viene copiato in un valore zval, sempre con un refcount di 0. Il blocco viene rilasciato, la chiamata a preg_match funziona su una copia dei dati, che è essa stessa una copia dei dati originali.
Cose da sapere:
La tabella hash
dell'archivio oggetti in cui sono archiviati i dati, thread-safe, si basa sulla tabella TsHash fornita con PHP da Zend.
L'archivio oggetti ha un blocco di lettura e scrittura, un ulteriore blocco di accesso è fornito per la TsHashTable tale che se necessario (e lo fa, var_dump / print_r, accesso diretto alle proprietà come il motore PHP vuole fare riferimento a loro) i pthreads possono manipolare la TsHashTable al di fuori dell'API definita.
I blocchi vengono mantenuti solo quando si verificano le operazioni di copia, quando le copie sono state eseguite, i blocchi vengono rilasciati, in un ordine ragionevole.
Questo significa:
Quando si verifica una scrittura, non solo viene trattenuto un blocco di lettura e scrittura, ma un blocco di accesso aggiuntivo. La tabella stessa è bloccata, non è possibile che un altro contesto possa bloccarla, leggerla, scriverla o influenzarla.
Quando si verifica una lettura, non solo viene mantenuto il blocco di lettura, ma anche il blocco di accesso aggiuntivo, di nuovo la tabella viene bloccata.
Nessun due contesti possono accedere fisicamente o contemporaneamente agli stessi dati dall'archivio oggetti, ma le scritture effettuate in qualsiasi contesto con un riferimento influenzeranno i dati letti in qualsiasi contesto con un riferimento.
Questa non è un'architettura condivisa e l'unico modo per esistere è la coesistenza. Quelli un po 'esperti lo vedranno, ci sono molte copie in corso qui, e si chiederanno se è una buona cosa. Molte operazioni di copiatura avvengono in un runtime dinamico, questa è la dinamica di un linguaggio dinamico. pthreads è implementato a livello dell'oggetto, perché si può ottenere un buon controllo su un oggetto, ma i metodi - il codice eseguito dal programmatore - hanno un altro contesto, privo di blocchi e copie - l'ambito del metodo locale. L'ambito dell'oggetto nel caso di un oggetto pthreads dovrebbe essere trattato come un modo per condividere dati tra contesti, questo è il suo scopo. Tenendo presente ciò, puoi adottare tecniche per evitare di bloccare l'archivio oggetti a meno che non sia necessario,
La maggior parte delle librerie ed estensioni disponibili per PHP sono thin wrapper di terze parti, la funzionalità di base di PHP è in un certo senso la stessa cosa. pthreads non è un involucro sottile attorno ai thread Posix; è un'API threading basata su thread Posix. Nell'implementazione di Thread in PHP non ha senso che gli utenti non capiscano o non possano usare. Non c'è motivo per cui una persona senza conoscenza di cosa sia o faccia un mutex non dovrebbe essere in grado di sfruttare tutto ciò che ha, sia in termini di abilità che di risorse. Un oggetto funziona come un oggetto, ma ovunque due contesti si scontrino altrimenti, pthreads fornisce stabilità e sicurezza.
Chiunque abbia lavorato in Java vedrà le somiglianze tra un oggetto pthreads e il threading in Java, quelle stesse persone non avranno alcun dubbio visto un errore chiamato ConcurrentModificationException - poiché suona un errore generato dal runtime java se due thread scrivono gli stessi dati fisici in concomitanza. Capisco perché esiste, ma mi sconcerta che con risorse economiche come sono, insieme al fatto che il runtime è in grado di rilevare la concorrenza nel momento esatto e unico che la sicurezza potrebbe essere raggiunta per l'utente, che sceglie di genera un errore potenzialmente fatale in fase di esecuzione anziché gestire l'esecuzione e l'accesso ai dati.
Nessun errore così stupido verrà emesso da pthreads, l'API è stata scritta per rendere il threading più stabile e compatibile possibile, credo.
Il multi-threading non è come usare un nuovo database, bisogna prestare molta attenzione a ogni parola del manuale e agli esempi forniti con pthreads.
Infine, dal manuale di PHP:
pthreads è stato ed è un esperimento con risultati abbastanza buoni. Qualunque delle sue limitazioni o caratteristiche può cambiare in qualsiasi momento; questa è la natura della sperimentazione. Le sue limitazioni - spesso imposte dall'implementazione - esistono per una buona ragione; lo scopo di pthreads è di fornire una soluzione utilizzabile per il multitasking in PHP a qualsiasi livello. Nell'ambiente in cui pthreads viene eseguito, alcune restrizioni e limitazioni sono necessarie per fornire un ambiente stabile.
Ecco un esempio di ciò che Wilco ha suggerito:
$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);
Fondamentalmente questo esegue lo script PHP dalla riga di comando, ma restituisce immediatamente il PID e quindi viene eseguito in background. (L'eco $! Assicura che non venga restituito nient'altro che il PID.) Ciò consente allo script PHP di continuare o uscire se lo si desidera. Quando l'ho usato, ho reindirizzato l'utente su un'altra pagina, dove ogni 5 a 60 secondi viene effettuata una chiamata AJAX per verificare se il report è ancora in esecuzione. (Ho una tabella per memorizzare gen_id e l'utente a cui è correlato.) Lo script check esegue quanto segue:
exec('ps ' . $pid , $processState);
if (count($processState) < 2) {
// less than 2 rows in the ps, therefore report is complete
}
C'è un breve post su questa tecnica qui: http://nsaunders.wordpress.com/2007/01/12/running-a-background-process-in-php/
In breve: sì, c'è il multithreading in php ma dovresti usare invece il multiprocessing.
C'è sempre un po 'di confusione sulla distinzione di thread e processi, quindi descriverò brevemente entrambi:
Puoi ottenere il calcolo parallelo creando nuovi processi (che contengono anche un nuovo thread) con php. Se i tuoi thread non richiedono molta comunicazione o sincronizzazione, questa è la tua scelta, poiché i processi sono isolati e non possono interferire con il lavoro reciproco. Anche se uno si blocca, ciò non riguarda gli altri. Se hai bisogno di molte comunicazioni, dovresti leggere sul "multithreading" o - purtroppo - prendere in considerazione l'uso di un altro linguaggio di programmazione, perché la comunicazione e la sincronizzazione tra processi introducono molta carnagione.
In php hai due modi per creare un nuovo processo:
lascia che il sistema operativo lo faccia per te : puoi dire al tuo sistema operativo di creare un nuovo processo ed eseguire un nuovo (o lo stesso) script php al suo interno.
per Linux puoi usare quanto segue o considerare la risposta di Darryl Hein :
$cmd = 'nice php script.php 2>&1 & echo $!';
pclose(popen($cmd, 'r'));
per Windows puoi usare questo:
$cmd = 'start "processname" /MIN /belownormal cmd /c "script.php 2>&1"';
pclose(popen($cmd, 'r'));
fai da te con un fork : php offre anche la possibilità di usare il fork attraverso la funzione pcntl_fork () . Un buon tutorial su come farlo può essere trovato qui, ma consiglio vivamente di non usarlo, dal momento che fork è un crimine contro l'umanità e soprattutto contro l'oop.
Con il multithreading tutti i tuoi thread condividono le loro risorse in modo da poter comunicare facilmente tra loro e sincronizzarle senza sovraccarico. Dall'altro lato devi sapere cosa stai facendo, poiché le condizioni di gara e gli deadlock sono facili da produrre ma molto difficili da eseguire il debug.
Il php standard non fornisce alcun multithreading ma esiste un'estensione (sperimentale) che in realtà lo fa - pthreads . La sua documentazione API ha persino trasformato in php.net . Con esso puoi fare alcune cose come puoi nei veri linguaggi di programmazione :-) in questo modo:
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();
}
Per Linux c'è una guida all'installazione proprio qui da StackOverflow.
Per Windows ce n'è uno ora:
Modifica [phpDirectory] /php.ini e inserisci la seguente riga
extension=php_pthreads.dll
Provalo con lo script sopra con un po 'di sonno o qualcosa proprio lì dove si trova il commento.
E ora il grande MA : sebbene funzioni davvero, php non era originariamente creato per il multithreading. Esiste una versione thread-safe di php e dalla v5.4 sembra quasi priva di bug ma l'utilizzo di php in un ambiente multi-thread è ancora scoraggiato nel manuale di php (ma forse non hanno appena aggiornato il loro manuale su questo, ancora). Un problema molto più grande potrebbe essere che molte estensioni comuni non sono thread-safe . Quindi potresti ottenere thread con questa estensione php ma le funzioni da cui dipendi non sono ancora thread-safe, quindi probabilmente incontrerai condizioni di gara, deadlock e così via nel codice che non hai scritto tu stesso ...
Puoi usare pcntl_fork () per ottenere qualcosa di simile ai thread. Tecnicamente si tratta di processi separati, quindi la comunicazione tra i due non è così semplice con i thread, e credo che non funzionerà se PHP viene chiamato da Apache.
Se qualcuno se ne frega, ho rianimato php_threading (non lo stesso dei thread, ma simile) e in realtà l'ho al punto in cui funziona (in qualche modo) bene!
pcntl_fork()
è quello che stai cercando, ma il suo processo di fork non è il threading. quindi avrai il problema dello scambio di dati. per risolverli è possibile utilizzare le funzioni dei semafori phps ( http://www.php.net/manual/de/ref.sem.php ) le code dei messaggi potrebbero essere un po 'più semplici all'inizio rispetto ai segmenti di memoria condivisa.
Comunque, una strategia che sto usando in un framework web che sto sviluppando che carica blocchi ad alta intensità di risorse di una pagina web (probabilmente con richieste esterne) parallela: sto facendo una fila di lavoro per sapere quali dati sto aspettando e poi faccio fork fuori dai lavori per ogni processo. una volta fatto memorizzano i loro dati nella cache apc in una chiave univoca a cui il processo genitore può accedere. una volta che ogni dato è lì, continua. sto usando un sempliceusleep()
l'attesa perché la comunicazione tra processi non è possibile in apache (i bambini perderanno la connessione con i loro genitori e diventeranno zombi ...). quindi questo mi porta all'ultima cosa: è importante uccidere se stessi ogni bambino! ci sono anche classi che eseguono il fork dei processi ma mantengono i dati, non li ho esaminati ma il framework zend ne ha uno e di solito eseguono un codice lento ma affidabile. Potete trovare qui:
http://zendframework.com/manual/1.9/en/zendx.console.process.unix.overview.html
penso che usano i segmenti shm! beh, ultimo ma non meno importante, c'è un errore su questo sito Web zend, un piccolo errore nell'esempio.
while ($process1->isRunning() && $process2->isRunning()) {
sleep(1);
}
should of course be:
while ($process1->isRunning() || $process2->isRunning()) {
sleep(1);
}
Esiste un'estensione di Threading in fase di sviluppo basata su PThreads che sembra molto promettente su https://github.com/krakjoe/pthreads
Solo un aggiornamento, sembra che i ragazzi di PHP stiano lavorando su thread di supporto ed è ora disponibile.
Ecco il link ad esso: http://php.net/manual/en/book.pthreads.php
Ho una classe di threading PHP che funziona perfettamente in un ambiente di produzione da oltre due anni.
EDIT: Questo è ora disponibile come libreria per compositori e come parte del mio framework MVC, Hazaar MVC.
So che questa è una domanda molto vecchia, ma potresti guardare http://phpthreadlib.sourceforge.net/
Comunicazione bidirezionale, supporto per Win32 e nessuna estensione richiesta.
Hai mai sentito parlare appserver
di techdivision?
È scritto in php e funziona come un appserver che gestisce i multithread per applicazioni php ad alto traffico. È ancora in beta ma molto promettente.
C'è la caratteristica piuttosto oscura, e presto da deprecare, chiamata tick . L'unica cosa per cui l'ho mai usato è consentire a uno script di catturare SIGKILL (Ctrl + C) e chiuderlo con grazia.
pcntl_fork()
) funzionerà se chiamato da Apache?