Я в основном знаком с Java, C и C++, в которых есть способы контролировать, чтобы только один поток обращался к ресурсу в любой момент времени. Сейчас ищу что-то похожее, но на PHP 5.x.
Чтобы сформулировать мою проблему на одном примере:
У меня есть ASCII-файл, в котором хранится только число, значение счетчика загрузки страницы. При развертывании приложения файл просто будет содержать 0. Для каждого доступа значение будет увеличиваться на единицу. Цель - отслеживать загрузку страниц.
Проблема возникает, когда многие пользователи одновременно обращаются к странице, содержащей счетчик. Когда поток A прочитал текущее значение, допустим, это 11, другой поток, который мы называем B, считывает значение, по-прежнему 11. Затем первый поток A увеличивает значение чтения и записывает 12 в файл и закрывает его. Затем второй поток B увеличивает значение чтения, которое было 11, получает 12 и записывает его в файл. В файле хранится значение 12, тогда как на самом деле должно было быть 13.
На другом языке программирования я бы решил это с помощью мьютекса. Я так понимаю, что в составе модулей есть мьютексы, разделяемая память и другие функции. Но мне нужно решение, которое работает «на большинстве серверов». Независимая платформа. Устанавливается на самых дешевых веб-хостингах. Есть ли хорошее решение этой проблемы? А если нет, то какой путь вы выберете при использовании база данных не вариант?






Вы можете попробовать php-вариант flock (http://www.php.net/flock)
Я бы вообразил что-то похожее (это предполагает, что файл /tmp/counter.txt уже существует и имеет счетчик в файле):
<?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);
}
?>
Ой, это остаток моей первоначальной разработки. Я собирался просто использовать fseek без ftruncate. Добавление пробелов гарантирует, что он удалит любые другие символы, которые были в строке (что более важно для уменьшения.) Отредактировано выше, поскольку оно больше не требуется.
Функция PHP flock () - это правильный путь. Однако вы должны сначала убедиться, что доступ все к файлу защищен вызовом flock (). PHP не будет проверять, заблокирован ли файл, пока вы не сделаете этого явным образом.
Концепция практически идентична мьютексам (защита общих ресурсов и т. д.), Но она достаточно важна, чтобы сделать особый акцент.
Информативный ответ с решением примера проблемы, спасибо! Я думаю, что вызов flock ($ fp, LOCK_UN) хорош, хотя fclose ($ fp) также снимает блокировку. У меня есть один вопрос: почему вы добавляете пробелы перед новой строкой в fwrite ($ fp, $ cntr. "\ N")?