php flock和fread和fwrite

时间:2012-08-05 20:28:30

标签: php locking file-locking flock

我看到人们像这样使用羊群:

if (!$fp = fopen($file_name, 'wb'))  
{  
    return FALSE;  
}  

if (flock($fp, LOCK_EX))  
{  
    fwrite($fp, serialize($data));  
    flock($fp, LOCK_UN);  
}

还有:

if (!$fp = @fopen($file_name, 'rb'))  
{  
    return FALSE;  
}  

flock($fp, LOCK_SH);  

$data = '';  

if (filesize($file_name) > 0)  
{  
    $data = unserialize(fread($fp, filesize($file_name)));  
}  

但其他人是否有机会在fopen来电和flock来电之间修改档案?以及fread

的相同问题

编辑:
为了澄清我为什么要问这个......我的问题基于代码here,在mysql缓存情况下,如果他们能够同时访问20个人,那么会阻止20个人所有人都可以介入fopen和flock之间?

这段代码是否万无一失?

2 个答案:

答案 0 :(得分:6)

你问:

  

是否有其他人可以在fopen调用和flock调用之间编辑文件?和fread一样的问题

是的,不,也许吧。简短回答:假设“是”并谨慎行事。

是的,因为传统的基于flock()的锁定只是 advice ,所以其他进程(甚至同一个进程)可以自由地忽略锁。在实践中,这不是问题,因为flock()由行为良好的客户端代码使用 - 在获得LOCK_SH之前不会读取,除非您在应用程序上获得LOCK_EX,否则不会写入 - 具体文件。

不,PHP的flock()实现在某些操作系统上可能强制,符合documentation,这可能也需要文件系统的支持(例如,与Linux下的mand选项。所以,其他进程无法忽视这些锁。

也许,因为PHP 5中的流子系统实现了操作系统提供的一些locking bookkeeping。例如,这可以防止相同的过程(但不是另一个过程)忽略其自身的其他咨询锁定。行为might surprise一些。即便如此,这种锁定在不相关的过程之间也不是强制性的。

为了便于携带,只需假设最弱的语义(上面的“是”)并将flock()限制在预先选择的特定于应用程序的锁定文件上的良好代码。

答案 1 :(得分:2)

第一个片段是万无一失的,如果你无法锁定文件,你就不会写。如果其他人在fopen()flock()之间编辑了文件,则您的文件句柄将指向最新的版本,因为fopen()绑定到流,而不是“快照”。

第二个示例无法保证正常工作,因为未检查flock()的返回值,因此如果您尚未获取锁定,则无论如何都将执行后续代码。

[edit]删除了读者锁无关紧的声明,实际上是这样,如下面的评论所述:)