这是一个简单的例子,突出了同时存在的危险:
<?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";
Run Code Online (Sandbox Code Playgroud)
如果附加是安全的,你应该得到一个包含100行的文件,所有这些行大约有10,000个字符长,并以整数开头.有时候,当你运行这个脚本时,这正是你得到的.有时,一些附加物会发生冲突,但它会受到损害.
你可以找到损坏的线条 grep '^[^0-9]' test.txt
这是因为在以下情况下,文件附加只是原子的:
如果您在日志追加期间对fwrite进行多次调用,或者您写的数量超过4k,则所有投注均已关闭.
现在,关于这是否重要:你是否可以在重载下的日志中有一些损坏的行?老实说,大多数时候这是完全可以接受的,你可以避免文件锁定的开销.
我确实有高性能的多线程应用程序,其中所有线程都在写入(追加)到单个日志文件.到目前为止,没有发现任何问题,每个线程每秒写入多次,没有任何东西丢失.我认为只是追加巨大的文件应该没有问题.但是如果你想修改已经存在的内容,特别是并发 - 我会选择锁定,否则会发生大混乱...