2010-05-27 17 views
15

Leggi alcuni testi sul blocco in PHP.
Tutti, principalmente, diretti a http://php.net/manual/en/function.flock.php.esclusione reciproca PHP (mutex)

Questa pagina parla dell'apertura di un file sul disco rigido !!

È davvero così? Voglio dire, questo rende il blocco molto costoso - significa che ogni volta che voglio bloccare dovrò accedere all'hard-disk) =

Posso più confortarmi con una notizia deliziosa?

Edit:

A causa di alcune risposte che ho ottenuto qui, voglio chiedere questo;
Il mio script verrà eseguito solo da un thread o più? Perché se è uno per uno, ovviamente non ho bisogno di un mutex. C'è una risposta concisa?

esattamente di cosa sto cercando di fare

Inviata da ircmaxell.
Questa è la storia:

Ho due server ftp. Voglio essere in grado di mostrare sul mio sito web quanti utenti online sono online.
Quindi, ho pensato che questi server ftp "POST" le loro statistiche su una certa pagina di script PHP. Supponiamo che l'URL di questa pagina sia "http://mydomain.com/update.php".

Nella pagina principale del sito Web ("http://mydomain.com/index.php") visualizzerò le statistiche cumulative (utenti online).

Questo è tutto.

Il mio problema è che non sono sicuro se, quando un server ftp aggiorna le sue statistiche mentre un altro lo fa, le informazioni si mescoleranno.
Come quando multi-threading; Due thread aumentano alcune variabili "int" allo stesso tempo. Non avverrà come previsto a meno che non si sincronizzi tra loro.
Quindi, avrò un problema? Sì no forse?

Possibile soluzione

Pensiero duro su di esso tutto il giorno, ho un'idea qui e voglio che dare la vostra opinione.
Come detto questi server ftp pubblicheranno le loro statistiche, una volta ogni 60 secondi.
Sto pensando di avere questo file "stats.php".
Sarà incluso nello script di aggiornamento che i server ftp visitano ("update.php") e nella pagina "index.php" dove i visitatori vedono quanti utenti sono online.
Ora, quando un server ftp si aggiorna, lo script su "update.php" modificherà "stats.php" con le nuove statistiche cumulative.
Prima leggerà le statistiche incluse in "stats.php", quindi accumulerà e quindi riscriverà quel file.

Se non sbaglio, PHP rileverà che il file ("stats.php") è stato modificato e carica quello nuovo. Corretta?

+0

PHP supporta anche il threading? Guardando attraverso l'API di PHP non vedo nulla che sembra essere correlato ai thread ... – tloach

+0

Per qualche ragione pensavo che PHP supporti il ​​threading, nel modo in cui eseguirà lo stesso script per diversi client simultaneamente. – Poni

+0

Quindi ho una variabile statica che manterrà alcuni dati, che viene aggiornato da diverse fonti e che viene inviato a diversi client. Questo potrebbe accadere simultaneamente, quindi ho bisogno di un modo per sincronizzare. – Poni

risposta

24

Bene, la maggior parte di PHP viene eseguita in uno spazio di processo diverso (esistono poche implementazioni di threading). Quello facile è il gregge. È garantito il funzionamento su tutte le piattaforme.

Tuttavia, se si compila in supporto, è possibile utilizzare alcune altre cose, come l'estensione del semaforo. (Compila PHP con --enable-sysvsem). Quindi, si può fare qualcosa di simile (nota, sem_acquire() dovrebbe bloccare Ma se non può, per qualche motivo, ritornerà falso.):

$sem = sem_get(1234, 1); 
if (sem_acquire($sem)) { 
    //successful lock, go ahead 
    sem_release($sem); 
} else { 
    //Something went wrong... 
} 

Le altre opzioni che avete, sono MySQL user level locksGET_LOCK('name', 'timeout') , o creando il tuo usando qualcosa come APC o XCache (Nota, questo non sarebbe un vero blocco, dal momento che potrebbero essere create condizioni di gara dove qualcun altro ottiene un blocco tra il tuo assegno e l'accettazione del lucchetto).

Modifica: Per rispondere alla tua domanda modificata:

Tutto dipende dalla configurazione del server. PHP Può essere eseguito multi-thread (dove ogni richiesta è servita da un thread diverso), o può essere eseguita multi-processo (dove ogni richiesta è servita da un processo diverso). Tutto dipende dalla configurazione del tuo server ...

È MOLTO raro che PHP possa servire tutte le richieste in serie, con un solo processo (e un thread) che serve tutte le richieste. Se stai usando CGI, è multiprocesso per impostazione predefinita. Se stai usando FastCGI, è probabile che sia multiprocesso e multi-thread. Se stai usando mod_php con Apache, poi dipende dal tipo di lavoratore:

  1. mpm_worker sarà sia multi-processo e multi-thread, con il numero di processi dettati dalla variabile ServerLimit.
  2. prefork sarà multi-processo
  3. perchild sarà multi-processo così

Modifica: Per rispondere alla tua seconda domanda modificata:

E 'abbastanza facile. Conservalo in un file:

function readStatus() { 
    $f = fopen('/path/to/myfile', 'r'); 
    if (!$f) return false; 
    if (flock($f, LOCK_SH)) { 
     $ret = fread($f, 8192); 
     flock($f, LOCK_UN); 
     fclose($f); 
     return $ret; 
    } 
    fclose($f); 
    return false; 
} 

function updateStatus($new) { 
    $f = fopen('/path/to/myfile', 'w'); 
    if (!$f) return false; 
    if (flock($f, LOCK_EX)) { 
     ftruncate($f, 0); 
     fwrite($f, $new); 
     flock($f, LOCK_UN); 
     fclose($f); 
     return true; 
    } 
    fclose($f); 
    return false; 
} 

function incrementStatus() { 
    $f = fopen('/path/to/myfile', 'rw'); 
    if (!$f) return false; 
    if (flock($f, LOCK_EX)) { 
     $current = fread($f, 8192); 
     $current++; 
     ftruncate($f, 0); 
     fwrite($f, $current); 
     flock($f, LOCK_UN); 
     fclose($f); 
     return true; 
    } 
    fclose($f); 
    return false; 
} 
+0

Spazio di processo diverso ancora posso avere una variabile statica (aka Singleton) che è condivisa tra tutti i client - come mai? – Poni

+0

Questo blocco di livello utente MySQL è piacevole ma richiede una connessione TCP e un'istanza/macchina MySQL. Meglio usare il blocco basato su file .. Grazie però! – Poni

+0

Non è possibile condividere una variabile tra più istanze di php. Bene, è possibile se lo si serializza e lo si archivia in un negozio globale (come APC, memcached, MySQL, ecc.). Ma ogni "cliente" creerebbe la propria istanza. Cosa stai cercando di fare esattamente? – ircmaxell

-2

PHP non supporta il multithreading, ogni richiesta (e quindi ogni script PHP) verrà eseguita in un solo thread (o anche processo, a seconda del modo in cui si esegue PHP).

+0

PHP supporta il multithreading, puoi farlo facilmente usando HTTP asincrono. – Slawek

+0

Attendi, HTTP asincrono è lato client, ciò non significa che il lato server sta eseguendo il multithreading (ogni richiesta asincrona viene eseguita come un singolo script PHP con thread). – Daff

+0

pcntl_fork ti permetterà di fare il vero multithreading, mi chiedo perché nessuno lo menzioni mai. – CodeReaper

0

Sì, è vero, poiché PHP viene eseguito da Apache e Apache è in grado di organizzare i thread di esecuzione come ritiene il migliore (vedere il vari modello di lavoro). Quindi, se si desidera accedere a una risorsa una alla volta, si può bloccare su un file (che è buono se si ha a che fare con lavori cron, ad esempio), oppure si basa sul meccanismo di transazione del database, sulle funzionalità ACID e sul blocco delle risorse del database, se hai a che fare con i dati.

0

Se hai bisogno di thread, stai usando la lingua sbagliata, sul serio.

+8

Sì, e non ho bisogno di threading. o sapere che un oggetto staticamente condiviso (diciamo un hit counter di tipo int) non sarà accessibile da più di un thread alla volta. Temo che PHP lo farà, perché MI ASSUMO che lo script PHP è eseguito da più di un thread sul server. Lo farà o no? Questa è la domanda. – Poni

1

La domanda è: dove memorizzerete le statistiche che i server FTP stanno spingendo con POST nel vostro file update.php? Se si tratta di un file locale, ircmaxell nel secondo post ha risposto. Puoi farlo anche con un mutex: le funzioni del semaforo. Un'altra soluzione è usare la tabella MyISAM MySQL per memorizzare le statistiche e usare qualcosa come update info_table set value = value + 1. Dovrebbe bloccare la tabella e serializzare le tue richieste e non avrai problemi.

0

Perché non basta che il file di aggiornamento scriva su un nome file basato sull'indirizzo IP del server ftp in arrivo. E il file php stats semplicemente legge e aggiunge i contenuti numerici di entrambi i file insieme.