Intereting Posts
новый оператор и опорная ошибка «Неустранимая ошибка: вызов неопределенного метода PHPUnit_Util_Filter :: addfiletofilter () в / usr / bin / phpunit в строке 48» Как отобразить правильный номер страницы? Проверка подлинности электронной почты с использованием регулярного выражения в PHP Должен ли я изменить $ _REQUEST на $ _POST Какое преимущество использует фреймворк, такой как CodeIgniter или CakePHP, с использованием PHP? конвертирование ВО ВРЕМЯ загрузки перед сохранением на сервере png / gif в jpg SEO дружественный URL вместо строки запроса .htaccess Развертывание новой реликвии на кедрах Героку (PHP) «Вызовите undefined .. mssql_connect» при использовании PHP в IIS? php filemtime, filectime, fileatime показывает различное значение Как эхо пользовательский объект в PHP? отправить PDF в браузер после вызова ajax RewriteRule не будет работать в файле .htaccess Magento перечисляет продукты, которые не входят в категорию

должен LOCK_EX для чтения и записи быть атомарным?

file_put_contents ( "file", "data", LOCK_EX ) 

для записи (что означает – блокировка и запись в режиме "

 file_get_contents ( "file", LOCK_EX ) 

для чтения (что означает – захват блокировки, а затем чтение)

это будет исключение? поднять ошибку? блокировать до блокировки? или, по крайней мере, должно ли это ? есть ли вероятность того, что php будет вести себя как этот день?

EDIT: я знаю, что можно использовать переименование – я бы хотел узнать ответ на этот вопрос …

Solutions Collecting From Web of "должен LOCK_EX для чтения и записи быть атомарным?"

Поскольку этот ответ длинный, вот резюме: Нет, file_get_contents() не является атомарным, так как он не соблюдает консультативные блокировки .

О блокировке файлов в PHP:

В PHP, хотя на платформе * nix блокировка файловой системы является только рекомендательной. В документах (Emphasis mine):

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 уважает файловые блокировки вообще …

Вопросы теории гораздо лучше работают на программистах, чем здесь.

На данный момент PHP не поддерживает блокировку атомного файла.

Проще говоря, PHP не поддерживает комбинированную операцию fopen и flock , поэтому всегда будет небольшое окно возможностей для другого процесса для блокировки файла, который ваш процесс также открыл, прежде чем ваш процесс сможет заблокировать его.

Сказав это, flock будет по умолчанию блокироваться до тех пор, пока блокировка не будет выпущена. Имейте в виду, что примечание ircmaxell о консультативных блокировках на Linux / BSD.

Примечание. Для процесса чтения вам может LOCK_SH вместо LOCK_EX , так что несколько потоков считывателей могут одновременно заблокировать его. Запись всегда должна выполняться с использованием LOCK_EX или повреждения данных риска.

Примечание 2: предыдущее примечание работает, потому что вы можете получать только общие блокировки, если нет эксклюзивных блокировок, но исключительная блокировка требует, чтобы блокировки не были доступны до блокировки.