2012-08-05 39 views
7

我看到一群使用人是这样的:PHP的羊群和FREAD和fwrite

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人从所有能够同时访问该文件,如果他们都能进入fopen和flock之间?

是代码万无一失吗?

回答

6

在评论解释你问:

是不是有机会,有人否则会在fopen调用和flock调用之间编辑文件?和fread相同的问题

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

是的,因为基于传统flock()的锁定仅仅是建议,所以其他进程(或甚至相同的进程)可以自由地忽略锁。在实践中,这不是问题,因为行为良好的客户端代码使用flock() - 直到获得LOCK_SH才会读取,而且除非获得了应用程序上的LOCK_EX,否则不会写入,特定的文件。

不,在PHP的实现羊群()可能对某些操作系统强制性,每documentation,这可能也需要从文件系统(例如,与Linux下mand选项)的支持。所以,其他进程不能忽视这些锁。

也许,PHP 5中的streams子系统实现了一些超出操作系统提供的locking bookkeeping。例如,这可能会阻止同一过程(而不是另一个过程)忽视其自己的其他咨询锁。行为might surprise一些。即便如此,这种锁定在不相关的过程之间也不是强制性的。对于可移植性,只需假定最弱的语义(上面的“是”)并将flock()限制在事先选择的特定于应用程序的锁文件上的良好行为代码。

+0

如果该缓存仅由该特定脚本使用,则不会发生任何情况。如果有人将文件从shell中删除 - 确实会发生不好的事情。 – favoretti 2012-08-05 20:59:56

+0

是的,但正如另一条评论所述,LOCK_EX并不是像某种方式强迫fread一样“不会返回”。 – pilcrow 2012-08-05 21:30:43

+0

如果您阅读了PHP站点上的评论,但实际上确实如此,尽管锁定是建议性的。也就是说,强制锁定,例如,Linux只能在明确支持它的文件系统上进行工作,并按照这种方式进行安装。 – favoretti 2012-08-05 21:35:02

2

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

第二个例子不能保证能正常工作,因为flock()的返回值没有被检查,所以如果你还没有获得这个锁,那么随后的代码将被执行。

[编辑]删除语句读锁不要紧,它实际上,如下:)

+0

我基于我的问题代码[** here,**](http://www.jongales.com/blog/2009/02/18/simple-file-based-php-cache-class /)在mysql缓存的情况下,在这种情况下,基于该类中的代码,什么能阻止20个人同时访问该文件? – qwertymk 2012-08-05 20:38:09

+0

对于阅读 - 没有什么,这很可能是你想要的,并发缓存读访问,而不是独占。对于编写,确切地说,获得的锁将阻止其他人写入缓存。那些代码完全困扰你的是什么? – favoretti 2012-08-05 20:41:14

+0

我想一个小问题,如果100,000个人都尝试设置相同的缓存文件,并且在fopen和flock之间调用20,000个,那么将会有19,999个不需要的fwrites,其中一些人也会做检查,看看缓存是新鲜的,并且会错过它获取的新文件时间。这甚至是一个问题吗? – qwertymk 2012-08-05 20:45:13