【问题标题】:php flock and fread and fwritephp羊群和fread和fwrite
【发布时间】:2012-08-05 20:28:30
【问题描述】:

我看到人们这样使用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个人同时访问文件进入fopen和flock之间?

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

【问题讨论】:

    标签: php locking file-locking flock


    【解决方案1】:

    你问:

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

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

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

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

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

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

    【讨论】:

    • 如果缓存仅由该特定脚本使用,则不会发生任何事情。如果有人从 shell 中破解文件——当然,坏事会发生。
    • 是的,但正如另一条评论所述,LOCK_EX 并非以某种方式强制fread“不返回任何内容”。
    • 如果您阅读 PHP 网站上的 cmets 到flock(),它实际上确实如此,尽管锁定是建议性的。话虽这么说,例如,Linux 上的强制锁定只能在使用明确支持它并被挂载的文件系统时才能实现。
    • 酷,为你的回答点赞,比我的要详细得多:)
    【解决方案2】:

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

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

    [edit] 删除了读取器锁定无关紧要的声明,实际上它确实如此,如下面的 cmets 中所述:)

    【讨论】:

    • 我基于代码here,提出问题在那个班?
    • 用于读取 - 没有,这很可能是您想要的,并发缓存读取访问,而不是独占访问。对于写入,正是获得的锁将阻止其他人写入缓存。这段代码到底是什么困扰着你?
    • 我猜是一个小问题,如果 100,000 人都尝试设置相同的缓存文件,并且在 fopen 和 flock 之间调用了 20,000 人,将会有 19,999 次不需要的 fwrite,其中一些人也会有检查缓存是否是新的,是否会错过它获得的新文件时间。这还有问题吗?
    • 您示例中代码的唯一问题是它不检查是否获取了共享锁。如果在 fopen() 和获取共享读取器锁(将锁定文件以进行写入)之间进行了写入,则后续的 fread() 将返回文件的最新状态,因为文件句柄是对文件流的引用。当您进行锁定读取时,不能有写入,因为写入部分中的flock() 将无法获取写入锁。
    • 另外,如果在您尝试读取时文件被锁定以进行写入,fread() 将不返回任何内容。这就是为什么要检查共享锁获取是否也成功的原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-29
    • 1970-01-01
    • 2012-09-28
    • 2019-05-30
    相关资源
    最近更新 更多