php стекается, и fread, и fwrite
Я вижу, как люди используют стадо вот так:
if (!$fp = fopen($file_name, 'wb'))
{
return FALSE;
}
if (flock($fp, LOCK_EX))
{
fwrite($fp, serialize($data));
flock($fp, LOCK_UN);
}
Также это:
if (!$fp = @fopen($file_name, 'rb'))
{
return FALSE;
}
flock($fp, LOCK_SH);
$data = '';
if (filesize($file_name) > 0)
{
$data = unserialize(fread($fp, filesize($file_name)));
}
Но разве нет шанса, что кто-то другой отредактирует файл между вызовом fopen
и вызовом flock
? и тот же вопрос для fread
ИЗМЕНИТЬ:
Чтобы прояснить, почему я спрашиваю об этом... Я основываю свой вопрос на коде здесь, В ситуации с кэшированием mysql, что может помешать 20 людям получить доступ к файлу одновременно, если все они смогут войти между фопеном и стадом?
Является ли этот код надежным?
2 answers
Вы спрашиваете:
есть ли вероятность, что кто-то другой отредактирует файл между вызовом fopen и вызовом flock? и тот же вопрос для фрида
Да, нет, может быть. Короткий ответ: предположите "да" и действуйте осторожно.
Да, в этой традиционной блокировке на основе flock() просто рекомендуется , поэтому другие процессы (или даже тот же процесс) могут игнорировать блокировки. На практике это не проблема, так как flock() используется корректный клиентский код - вы не читаете, пока не получите LOCK_SH, и вы не пишете, если не получили LOCK_EX - файлы, относящиеся к конкретному приложению.
Нет, в том, что реализация PHP flock() может быть обязательной в определенных операционных системах, согласно документации , которая также может потребовать поддержки от файловой системы (например, как с манд опция под Linux). Таким образом, другие процессы не могли игнорировать эти блокировки.
Может быть, в что подсистема потоков в PHP 5 реализует некоторую блокировку бухгалтерского учета помимо того, что предусмотрено операционной системой. Это может, например, помешать одному и тому же процессу (но не другому) игнорировать свои собственные в противном случае рекомендательные блокировки. Поведение может некоторых удивить . Тем не менее, такого рода блокировка не будет обязательной между несвязанными процессами.
Для переносимости просто предположите самую слабую семантику ("да" выше) и ограничьте flock() хорошо себя вести код для файлов блокировки конкретного приложения, выбранных заранее.
Первый фрагмент защищен от ошибок, если вы не можете заблокировать файл, вы не пишете. Если кто-то другой редактировал файл между fopen()
и flock()
, ваш дескриптор файла будет указывать на последнее воплощение, поскольку fopen()
привязывается к потоку, а не к "снимку".
Второй пример не гарантированно сработает, потому что возвращаемое значение flock()
не проверено, поэтому, если вы не получили блокировку, последующий код будет выполнен в любом случае.
[редактировать] удалено утверждение, что блокировка чтения не имеет значения, на самом деле это имеет значение, как объяснено в комментариях ниже:)