| |
а самом деле ситуация далеко не так
пла-
чевна. Сейчас я постараюсь понятным языком разъяснить все, что касается
блокиро-
вок в языке PHP. Что же из себя представляют понятия исключительная блокировка
и
разделяемая блокировка?
Исключительная блокировка
Вернемся к нашему примеру с процессами-писателями. Каждый такой процесс стра-
стно желает, чтобы в некоторый момент (точнее, когда он уже почти готов начать
писать) он был единственным, кому разрешена запись в файл.
Он хочет стать исключительным.
Отсюда и название блокировки, которую процесс должен для себя установить. Вы-
звав функцию flock($f,LOCK_EX), он может быть абсолютно уверен, что все ос-
тальные процессы не начнут без разрешения писать в файл, пока он не выполнит
все
свои действия и не вызовет flock($f, LOCK_UN) или не закроет файл.
Откуда такая уверенность? Дело в том, что если в данный момент наш процесс не
единственный претендент на запись, операционная система просто не выпустит его
из "внутренностей" функции flock(), т. е. не допустит его продолжения, пока
про-
цесс-писатель не станет единственным. Момент, когда процесс, использующий ис-
ключительную блокировку, становится активным, знаменателен еще и тем, что все
остальные процессы-писатели ожидают (все в той же функции flock()), когда же
он, наконец, закончит свою работу с файлом. Как только это произойдет,
операцион-
ная система выберет следующий исключительный процесс, и т. д.
Что ж, давайте теперь рассмотрим, как в общем случае должен быть устроен
процесс-
писатель, желающий установить для себя исключительную блокировку (листинг
15.2).
Листинг 15.2. Модель процесса с исключительной блокировкой
// инициализация
// . . .
$f=fopen($f,"a+") or die("Не могу открыть файл на запись!");
flock($f,LOCK_EX); // ждем, пока мы не станем единственными
// В этой точке мы можем быть уверены, что только эта
// программа работает с файлом
Глава 15. Работа с файлами 263
// . . .
fflush($f); // записываем все изменения на диск
flock($f,LOCK_UN); // говорим, что мы больше не будем работать с файлом
fclose($f);
// Завершение
// . . .
?>
Заметьте, что при открытии файла мы использовали не деструктивный режим w (ко-
торый удаляет файл, если он существовал), а более "мягкий" — a+. Это неспроста.
Посудите сами: удаление файла идеологически есть изменение его содержимого. Но
мы не должны этого делать до получения исключительной блокировки (вспомните
пример со светофором)! Поэтому, если вам нужно обязательно каждый раз стирать
содержимое файла, ни в коем случае не используйте режим открытия w — применяй-
те a+ и функцию ftruncate(), описанную выше. Например:
$f=fopen($f,"a+") or die("Не могу открыть файл на запись!");
flock($f,LOCK_EX); // ждем, пока мы не станем единственными
ftruncate($f,0); // очищаем все содержимое файла
Зачем мы используем fflush() перед тем, как разблокировать файл? Все
очень просто: отключение блокировки не ведет к сбросу внутреннего файлово-
го буфера, т. е. некоторые изменения могут быть "сброшены" в файл уже после
того, как блокировка будет снята. Мы, разумеется, этого не хотим, вот и за-
ставляем PHP принудительно записать все изменения на диск.
Устанавливайте исключительную блокировку, когда вы собираетесь изменять
файл. Всегда используйте при этом режим открытия r, r+ или a+. Никогда не
применяйте режим w. Снимайте блокировку так рано, как только сможете, и не
забывайте перед этим вызвать fflush().
Разделяемая блокировка
Мы решили ровно половину нашей задачи. Действительно, теперь данные из не-
скольких процессов-писателей не будут перемешиваться, но как быть с читателями?
А вдруг процесс-читатель захочет прочитать как раз из того места, куда пишет
про-
цесс-писатель? В этом случае он, очевидно, получит "половинчатые" данные. То
есть,
данные неверные. Как же быть?
Существуют два метода обхода этой проблемы. Первый — это использовать все ту
же исключительную блокировку. Действительно, кто сказал, что исключительную
Часть IV. Стандартные функции PHP 264
блокировку можно применять только в процессах, изменяющих файл? Ведь функция
flock() не знает, что будет выполнено с файлом, для которого она вызвана.
Однако
этот метод
|
|