7

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

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


编辑:
为了澄清我为什么要问这个......我的问题是基于这里的代码,在 mysql 缓存情况下,如果他们都能够阻止 20 个人同时访问该文件,有什么办法可以在fopen和flock之间进入吗?

那个代码是万无一失的吗?

4

2 回答 2

6

你问:

其他人没有机会在 fopen 调用和flock 调用之间编辑文件吗?和 fread 相同的问题

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

是的,传统的基于flock() 的锁定只是建议性的,因此其他进程(甚至是同一个进程)可以随意忽略锁定。实际上,这不是问题,因为flock() 被行为良好的客户端代码使用——在获得LOCK_SH之前你不会阅读,除非你获得LOCK_EX,否则你不会写——在应用程序上——具体文件。

不,因为根据文档, PHP 的flock() 实现可能在某些操作系统上是强制性的,这可能还需要文件系统的支持(例如,与Linux 下的mand选项一样)。因此,其他进程不能忽视这些锁。

也许,因为 PHP 5 中的流子系统实现了一些超出操作系统提供的锁定簿记。例如,这可能会阻止同一个进程(但不是另一个进程)忽略它自己的其他建议锁。这种行为可能会让一些人感到惊讶。即便如此,这种锁定在不相关的进程之间也不是强制性的。

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

于 2012-08-05T20:55:56.527 回答
2

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

第二个例子不保证有效,因为flock()没有检查返回值,所以如果你没有获取锁,后面的代码无论如何都会执行。

[编辑] 删除了读者锁定无关紧要的声明,它确实如此,如下面的评论中所述:)

于 2012-08-05T20:33:38.513 回答