Question

Je connais surtout Java, C et C ++, dans lesquels il existe des moyens de contrôler qu'un seul thread accède à une ressource à un moment donné. Maintenant, je suis à la recherche de quelque chose de similaire, mais en PHP 5.x.

Pour formuler mon problème avec un exemple:

J'ai un fichier ASCII qui ne stocke qu'un nombre, la valeur d'un compteur de chargement de page. Lors du déploiement de l'application, le fichier contiendra simplement un 0. Pour chaque accès, la valeur sera incrémentée de un. L’objectif est de garder une trace des chargements de pages.

Le problème survient lorsque plusieurs utilisateurs accèdent simultanément à la page contenant le compteur. Lorsque le thread A a lu la valeur actuelle, disons que c'est 11, un autre thread que nous appelons B lit la valeur, toujours 11. Ensuite, le premier thread A incrémente la valeur lue, écrit 12 dans le fichier et le ferme. Ensuite, le deuxième thread B, incrémente la valeur lue, qui était de 11, obtient 12 et l’écrit dans le fichier. La valeur 12 est stockée dans le fichier alors qu’elle aurait dû être 13.

Dans un autre langage de programmation, j'aurais résolu ce problème en utilisant un mutex. Je comprends qu’il existe des mutex, de la mémoire partagée et d’autres fonctionnalités dans le cadre de modules. Mais je voudrais une solution qui fonctionne sur "la plupart des serveurs". là-bas. Plateforme indépendante. Installé sur la plupart des hébergeurs Web bon marché. Existe-t-il une bonne solution à ce problème? Et s’il n’y en avait pas, quelle solution choisiriez-vous si l’utilisation d’une base de données n’était pas une option ?

Était-ce utile?

La solution

Vous pouvez essayer la variante de php de php ( http://www.php.net/flock ).

J'envisagerais quelque chose de similaire à (cela suppose que le fichier /tmp/counter.txt existe déjà et qu'il ait un compteur dans le fichier):

<?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);
}

?>

Autres conseils

La fonction flock () de PHP est la voie à suivre. Cependant, vous devez vous assurer que tous les accès au fichier sont d'abord protégés par un appel à flock (). PHP ne vérifiera pas si le fichier est verrouillé à moins que vous ne le demandiez explicitement.

Le concept est pratiquement identique à celui des mutex (protection des ressources partagées, etc.), mais il est suffisamment important pour porter une attention particulière.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top