PHP exclusión mutua(mutex)
mutual-exclusion (4)
Lee algunos textos sobre bloqueo en PHP.
Todos ellos, principalmente, dirigidos a http://php.net/manual/en/function.flock.php .
¡Esta página habla de abrir un archivo en el disco duro!
¿Es realmente así? Quiero decir, esto hace que el bloqueo sea realmente costoso; significa que cada vez que quiera bloquearlo tendré que acceder al disco duro) =
¿Ya me puede consolar con una noticia encantadora?
Editar:
Debido a algunas respuestas que tengo aquí, quiero preguntar esto;
¿Mi script se ejecutará solo por un hilo, o varios? Porque si es de uno, obviamente no necesito un mutex. ¿Hay una respuesta concisa?
¿Qué es exactamente lo que estoy tratando de hacer?
Preguntado por ircmaxell.
Esta es la historia:
Tengo dos servidores ftp. Quiero poder mostrar en mi sitio web cuántos usuarios en línea están en línea.
Entonces, pensé que estos servidores ftp "POSTARÁN" sus estadísticas a una determinada página de script PHP. Supongamos que la URL de esta página es " http://mydomain.com/update.php ".
En la página principal del sitio web (" http://mydomain.com/index.php ") mostraré las estadísticas acumuladas (usuarios en línea).
Eso es.
Mi problema es que no estoy seguro si, cuando un servidor ftp actualiza sus estadísticas mientras que otro lo hace también, la información se mezclará.
Como cuando multi-threading; Dos hilos aumentan alguna variable "int" al mismo tiempo. No sucederá como se espera a menos que se sincronice entre ellos.
Entonces, ¿tendré un problema? ¿Si no talvez?
Solución posible
Pensándolo bien todo el día, tengo una idea aquí y quiero que dé su opinión.
Como se dijo, estos servidores ftp publicarán sus estadísticas, una vez cada 60 segundos.
Estoy pensando en tener este archivo "stats.php".
Se incluirá en el script de actualización al que van los servidores ftp ("update.php") y en la página "index.php" donde los visitantes ven cuántos usuarios están en línea.
Ahora, cuando se actualiza un servidor ftp, la secuencia de comandos en "update.php" modificará "stats.php" con las nuevas estadísticas acumulativas.
Primero leerá las estadísticas incluidas en "stats.php", luego se acumulará y luego reescribirá ese archivo.
Si no me equivoco, PHP detectará que el archivo ("stats.php") se modificó y cargará el nuevo. ¿Correcto?
Bueno, la mayoría de PHP se ejecuta en un espacio de proceso diferente (hay pocas implementaciones de subprocesos). La fácil es el rebaño. Está garantizado para trabajar en todas las plataformas.
Sin embargo, si compilas en soporte, puedes usar algunas otras cosas como la extensión Semaphore. (Compilar PHP con --enable-sysvsem). Luego, puedes hacer algo como (nota, sem_acquire () debería bloquear. Pero si no puede por alguna razón, devolverá false):
$sem = sem_get(1234, 1);
if (sem_acquire($sem)) {
//successful lock, go ahead
sem_release($sem);
} else {
//Something went wrong...
}
Las otras opciones que tiene, son los bloqueos de nivel de usuario de MySQL GET_LOCK(''name'', ''timeout'')
, o crear su propio uso de algo como APC o XCache (Tenga en cuenta que esto no sería un verdadero bloqueo, ya que las condiciones de la carrera podrían ser creado donde alguien más obtiene un bloqueo entre su cheque y la aceptación del bloqueo).
Editar: Para responder a su pregunta editada:
Todo depende de la configuración de su servidor. PHP Puede ejecutarse en múltiples subprocesos (donde cada solicitud es atendida por un subproceso diferente), o puede ejecutarse en múltiples procesos (donde cada solicitud es atendida por un proceso diferente). Todo depende de la configuración de su servidor ...
Es MUY raro que PHP sirva todas las solicitudes en serie, con un solo proceso (y un hilo) que sirve todas las solicitudes. Si está utilizando CGI, entonces es multiproceso de forma predeterminada. Si está utilizando FastCGI, es probable que sea multiproceso y multiproceso. Si está usando mod_php con Apache, entonces depende del tipo de trabajador:
- mpm_worker será multiproceso y multiproceso, con el número de procesos dictados por la variable ServerLimit.
- Prefork será multiproceso
- perchild será multiproceso también
Editar: Para responder a su segunda pregunta editada:
Es bastante facil Guárdalo en un archivo:
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;
}
La pregunta es: ¿Dónde almacenará las estadísticas que los servidores FTP están enviando con POST a su archivo update.php? Si es un archivo local, ircmaxell en la segunda publicación te ha respondido. También puede hacer esto con un mutex: las funciones del semáforo. Otra solución es usar la tabla MySQL MyISAM para almacenar las estadísticas y usar algo como update info_table set value = value + 1
. Debería bloquear la tabla y serializar sus solicitudes, y no tendrá problemas.
PHP no admite subprocesos múltiples, cada solicitud (y, por lo tanto, cada secuencia de comandos PHP) se ejecutará en un solo hilo (o incluso en el proceso, dependiendo de la forma en que se ejecuta PHP).
Sí, es cierto, ya que PHP es ejecutado por Apache, y Apache puede organizar los subprocesos de ejecución que considere los mejores (vea los distintos modelos de trabajadores). Por lo tanto, si desea acceder a un recurso de uno en uno, puede bloquear un archivo (lo cual es bueno si está tratando con trabajos de cron, por ejemplo) o confiar en el mecanismo de transacción de la base de datos, las características de ACID y el bloqueo de recursos de la base de datos. Si se trata de datos.