file_put_contents ( "file", "data", LOCK_EX )
用于写入(意味着 - 获取锁并写入)
file_get_contents ( "file", LOCK_EX )
用于读取(也就是说 - 获取锁然后读取)
它会抛出异常吗?引发错误?阻塞直到获得锁? 或者至少 - 应该吗? PHP有可能某一天会像这样表现吗?
编辑:我知道可以使用rename,但我想知道答案...
file_get_contents()
不是原子的,因为它不遵守建议锁定。
关于PHP中的文件锁:-o mand
的特殊挂载选项来启用强制锁定(但这并不常用,并且可能会有性能损失)。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
:回答你的另一个具体问题,首先,file_get_contents
没有LOCK_EX
参数。所以你不能传递它。
现在,看一下源代码,我们可以看到函数file_get_contents
在第521行被定义。当你传递file_put_contents('file', 'txt', LOCK_EX);
时,与内部函数php_stream_lock
相比,没有调用这个函数。
那么,让我们来测试一下吧:
在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);
var_dump(file_get_contents('test.txt'));
file2.php
时,它会立即返回。因此,看起来file_get_contents
根本不尊重文件锁定...if
语句之外使用flock($f, LOCK_UN)?为什么要在第一次没有锁定的情况下解锁呢? - Pacerier理论问题在程序员上的效果比这里要好得多。
目前,PHP不支持原子文件锁定。
简而言之,PHP不支持合并的fopen
和flock
操作,因此在您的进程可以锁定它之前,另一个进程将始终有一个小的机会来锁定您的进程也已经打开的文件。
话虽如此,flock
默认情况下会阻塞,直到锁定被释放。不过请记住关于Linux/BSD上的咨询锁的ircmaxell的注意事项。
注意:对于读取进程,您可能希望将其设置为LOCK_SH
,而不是LOCK_EX
,以便多个读取线程可以同时锁定它。写入必须始终使用LOCK_EX
或者面临数据损坏的风险。
LOCK_SH
的缺点之一。如果你知道会有很多读者不断访问它,就将读取器代码也切换到 LOCK_EX
,或者使用专为此类用例编写的数据库。 - Powerlordc
和c+
的fopen标志呢? - Pacerier
fopen
来获取文件锁,一旦获得了这个锁,你就可以使用file_get_contents
函数。因为获取LOCK_SH
仅仅阻止其他PHP进程获取LOCK_EX
,所以file_get_contents
不会返回部分写入/修改的文件(前提是所有的PHP文件访问都严格使用flock
)。 - Lee Kowalkowski