Поскольку этот ответ длинный, вот краткое изложение: Нет, file_get_contents()
не является атомарным, поскольку не учитывает консультативные блокировки .
О блокировках файлов в PHP:
В PHP, на платформе * nix блокировка файловой системы носит рекомендательный характер.Согласно документам (выделение у меня):
PHP поддерживает переносимый способ блокировки файлов целиком (то есть все программы доступа к должны использовать одно и то же).способ блокировки или не будет работать ).По умолчанию эта функция будет блокироваться до тех пор, пока не будет запрошена блокировка;этим можно управлять (на платформах, отличных от Windows) с помощью параметра LOCK_NB, описанного ниже.
Так что, пока все процессы, которые обращаются к файлу, используют этот метод блокировки, выхорошо.
Однако, если вы пишете статический HTML-файл с помощью нормального веб-сервера, блокировка будет игнорироваться.В середине записи, если поступит запрос, Apache будет обслуживать частично записанный файл.Блокировки не будут влиять на другой процесс, читающий блокировку.
Единственное реальное исключение - если вы используете специальную опцию монтирования -o mand
в файловой системе, чтобы включить обязательную блокировку (но на самом деле она используется не очень часто).и может иметь снижение производительности).
Прочтите Блокировка файлов для получения дополнительной информации.А именно раздел под Unix :
Это означает, что взаимодействующие процессы могут использовать блокировки для координации доступа к файлу между собой, но программы также могут игнорировать блокировки и получать доступ к файлулюбым способом, который они выберут.
Итак, в заключение, использование LOCK_EX
создаст консультативную блокировку файла.Любая попытка чтения файла блокируется, только если читатель уважает и / или проверяет блокировку.Если они этого не делают, блокировка будет игнорироваться (так как это может быть).
Попробуйте.В одном процессе:
file_put_contents('test.txt', 'Foo bar');
$f = fopen('test.txt', 'a+');
if (flock($f, LOCK_EX)) {
sleep(10);
fseek($f, 0);
var_dump(fgets($f, 4048));
flock($f, LOCK_UN);
}
fclose($f);
И пока он спит, назовите это:
$f = fopen('test.txt', 'a+');
fwrite($f, 'foobar');
fclose($f);
Вывод будет foobar
...
О file_get_contents
в частности:
К вашему другому конкретному вопросу, во-первых, нет параметра LOCK_EX
для file_get_contents
.Таким образом, вы не можете передать это.
Теперь, глядя на исходный код , мы можем увидеть функцию file_get_contents
, определенную в строке 521. Нет вызовов для внутренней функцииphp_stream_lock
как и при передаче file_put_contents('file', 'txt', LOCK_EX);
, определенной в строке 589 того же файла.
Итак, давайте проверим это:
В file1.php:
file_put_contents('test.txt', 'Foo bar');
$f = fopen('test.txt', 'a+');
if (flock($f, LOCK_EX)) {
sleep(10);
fseek($f, 0);
var_dump(fgets($f, 4048));
flock($f, LOCK_UN);
}
fclose($f);
В file2.php:
var_dump(file_get_contents('test.txt'));
При запуске file2.php
немедленно возвращается.Так что нет, не похоже, что file_get_contents
вообще учитывает блокировки файлов ...