应该在两个LOCK_EX上读取&写原子的? [英] should LOCK_EX on both read & write be atomic?

查看:104
本文介绍了应该在两个LOCK_EX上读取&写原子的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

用于书写(这意味着-获取锁定并进行书写)

for writing (which means - aquire lock and write)

file_get_contents ( "file", LOCK_EX )

阅读(这意味着-获取锁然后阅读)

for reading (which means - aquire lock and then read)

会抛出异常吗?引发错误?阻止直到获得锁? 或至少-应该吗? php是否有可能像这一天一样表现?

will it throw exception? raise an error? block until lock is aquired? or at least - should it? is there a chance that php will behave like this one day?

我知道可以使用重命名-我想知道答案...

i know that it is possible to use rename - i'd like to know answer to this...

推荐答案

由于这个答案很长,所以这里是摘要:不,file_get_contents()不是原子的,因为它不考虑咨询锁..

Since this answer is long, here's the summary: No, file_get_contents() is not atomic as it does not respect advisory locks.

在PHP中,在* nix平台上,文件系统锁定仅是建议性的.根据文档(强调我的观点):

In PHP, while on a *nix platform, filesystem locking is advisory only. Per the docs (Emphasis mine):

PHP支持以咨询方式锁定完整文件的可移植方式(这意味着所有正在访问的程序都必须使用相同的锁定方式,否则将无法使用).默认情况下,此功能将阻塞,直到获得请求的锁为止;否则,此功能将保留.可以通过下面介绍的LOCK_NB选项控制(在非Windows平台上).

PHP supports a portable way of locking complete files in an advisory way (which means all accessing programs have to use the same way of locking or it will not work). By default, this function will block until the requested lock is acquired; this may be controlled (on non-Windows platforms) with the LOCK_NB option documented below.

因此,只要所有访问文件的进程都使用这种锁定方法,就可以了.

So, as long as all of the processes that are accessing the file use this method of locking, you're fine.

但是,如果您使用健全的Web服务器编写静态HTML文件,则该锁将被忽略.在写入过程中,如果有请求传入,Apache将提供部分写入的文件.锁不会对其他读取该锁的进程产生影响.

However, if you're writing a static HTML file with a sane webserver, the lock will be ignored. In the middle of the write, if a request comes in, Apache will serve the partially written file. The locks will have no effect on the other process reading the lock.

唯一真正的例外是,如果在文件系统上使用-o mand的特殊安装选项来启用强制锁定(但这并没有真正使用很多,并且可能会降低性能).

The only real exception is if you use the special mount option of -o mand on the filesystem to enable mandatory locking (but that's not really used much, and can have a performance penalty).

请阅读文件锁定,以了解更多信息.即 Unix 下的部分:

Have a read on File Locking for some more information. Namely the section under Unix:

这意味着合作进程可以使用锁来协调彼此之间对文件的访问,但是程序也可以随意忽略锁并以他们选择的任何方式访问文件.

This means that cooperating processes may use locks to coordinate access to a file among themselves, but programs are also free to ignore locks and access the file in any way they choose to.

因此,总而言之,使用LOCK_EX将在文件上创建建议锁定.仅当读者尊重和/或检查锁时,任何尝试读取文件的尝试才会阻止.如果不这样做,则将忽略该锁定(因为可以这样做).

So, in conclusion, using LOCK_EX will create an advisory lock on the file. Any attempt to read the file will block only if the reader respects and/or checks for the lock. If they do not, the lock will be ignored (since it can be).

尝试一下.在一个过程中:

Try it out. In one process:

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);

在它睡觉的时候,叫这个:

And while it's sleeping, call this:

$f = fopen('test.txt', 'a+');
fwrite($f, 'foobar');
fclose($f);

输出将为foobar ...

对于您的其他特定问题,首先,对于LOCK_EX参数="noreferrer"> file_get_contents .所以你不能传递它.

To your other specific question, first off, there is no LOCK_EX parameter to file_get_contents. So you can't pass that in.

现在,查看源代码,我们可以看到在第521行定义的函数file_get_contents.与传递在同一文件的第589行定义的file_put_contents('file', 'txt', LOCK_EX);一样,没有对内部函数php_stream_lock的调用.

Now, looking at the source code, we can see the function file_get_contents defined on line 521. There are no calls to the internal function php_stream_lock as there are when you pass file_put_contents('file', 'txt', LOCK_EX); defined on line 589 of the same file.

那么,让我们对其进行测试吧:

So, let's test it, shall we:

在file1.php中:

In 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中:

In file2.php:

var_dump(file_get_contents('test.txt'));

运行时,file2.php立即返回.所以不,看来file_get_contents根本没有遵守文件锁定...

When run, file2.php returns immediately. So no, it doesn't appear that file_get_contents respects file locks at all...

这篇关于应该在两个LOCK_EX上读取&写原子的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆