Вот простой пример, который подчеркивает опасность одновременной игры:
<?php
for($i = 0; $i < 100; $i++) {
$pid = pcntl_fork();
//only spawn more children if we're not a child ourselves
if(!$pid)
break;
}
$fh = fopen('test.txt', 'a');
//The following is a simple attempt to get multiple threads to start at the same time.
$until = round(ceil(time() / 10.0) * 10);
echo "Sleeping until $until\n";
time_sleep_until($until);
$myPid = posix_getpid();
//create a line starting with pid, followed by 10,000 copies of
//a "random" char based on pid.
$line = $myPid . str_repeat(chr(ord('A')+$myPid%25), 10000) . "\n";
for($i = 0; $i < 1; $i++) {
fwrite($fh, $line);
}
fclose($fh);
echo "done\n";
Если добавления безопасны, вы должны получить файл с 100 строками, каждая из которых имеет длину около 10 000 символов, и начинающиеся с целого числа. И иногда, когда вы запускаете этот скрипт, это именно то, что вы получите. Иногда несколько добавок конфликтуют, и, тем не менее, они искажаются.
Вы можете найти поврежденные строки с помощью grep '^[^0-9]' test.txt
Это потому, что добавление файла является атомарным, если :
- Вы делаете один вызов fwrite ()
- и что fwrite () меньше, чем PIPE_BUF (где-то около 1-4k)
- и вы пишете в полностью POSIX-совместимую файловую систему
Если вы делаете более одного вызова fwrite во время добавления журнала или пишете больше, чем около 4k, все ставки выключены.
Теперь о том, имеет ли это значение: нормально ли вам иметь несколько поврежденных строк в вашем журнале под большой нагрузкой? Честно говоря, в большинстве случаев это вполне приемлемо, и вы можете избежать накладных расходов на блокировку файлов.