Pregunta

Estoy mayormente familiarizado con Java, C y C ++ en el que hay formas de controlar que solo un hilo acceda a un recurso en un momento dado. Ahora estoy buscando algo similar pero en PHP 5.x.

Para formular mi problema con un ejemplo:

Tengo un archivo ASCII que solo almacena un número, el valor de un contador de carga de página. En la implementación de la aplicación, el archivo simplemente tendrá un 0. Para cada acceso, el valor se incrementará en uno. El objetivo es realizar un seguimiento de las cargas de página.

El problema surge cuando muchos usuarios acceden simultáneamente a la página que contiene el contador. Cuando el hilo A ha leído el valor actual, digamos que es 11, otro hilo que llamamos B lee el valor, aún 11. Entonces el primer hilo A incrementa el valor leído y escribe 12 en el archivo y lo cierra. Luego, el segundo hilo B, incrementa el valor de lectura, que era 11, obtiene 12 y lo escribe en el archivo. El valor 12 se almacena en el archivo, cuando realmente debería haber sido 13.

En otro lenguaje de programación, habría resuelto esto usando un mutex. Entiendo que hay mutexes, memoria compartida y otras funcionalidades como parte de los módulos. Pero me gustaría una solución que funcione en la mayoría de los servidores allí afuera. Plataforma independiente. Instalado en la mayoría de los servidores web baratos. ¿Hay una buena solución a este problema? Y si no lo hay, ¿qué camino tomaría si usar una base de datos no es una opción ?

¿Fue útil?

Solución

Puede probar la variante de flock de php ( http://www.php.net/flock )

Imaginaría algo similar a (esto supone que el archivo /tmp/counter.txt ya existe y tiene un contador en el archivo):

<?php

$fp = fopen("/tmp/counter.txt", "r+");

echo "Attempt to lock\n";
if (flock($fp, LOCK_EX)) {
  echo "Locked\n";
  // Read current value of the counter and increment
  $cntr = fread($fp, 80);
  $cntr = intval($cntr) + 1;

  // Pause to prove that race condition doesn't exist
  sleep(5);

  // Write new value to the file
  ftruncate($fp, 0);
  fseek($fp, 0, SEEK_SET);
  fwrite($fp, $cntr);
  flock($fp, LOCK_UN); // release the lock
  fclose($fp);
}

?>

Otros consejos

La función flock () de PHP es la ruta a seguir. Sin embargo, debe asegurarse de que los todos accesos al archivo estén protegidos por una llamada a flock () primero. PHP no verificará si el archivo está bloqueado a menos que explícitamente hagas la llamada para hacerlo.

El concepto es prácticamente idéntico al de mutexes (protección de recursos compartidos, etc.), pero es lo suficientemente importante como para tener un énfasis especial.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top