【问题标题】:is_dir fail when executed in parallel with the script creating the diris_dir 在与创建目录的脚本并行执行时失败
【发布时间】:2016-12-31 20:08:02
【问题描述】:

编辑:我的问题来自 Firefox 的“智能”行为。如果您在两个不同的选项卡上调用同一页面,它会在第一个完成后自动启动第二个。如果要并行执行,则必须添加不同的参数。

正在尝试使用目录创建互斥锁。例如:

$dir = 'test' ;
echo is_dir($dir) ;
mkdir($dir)
wait(30)
rmdir($dir)

在浏览器中,我调用脚本,几秒钟后在另一个选项卡上调用相同的脚本。

is_dir 返回 false,第二次调用时 mkdir 没有错误 在磁盘上,目录是使用第一个脚本创建的,并一直保留到第二个结束。

如果我在命令行上一个接一个地调用这两个脚本,我就有了
预期结果 is_dir 为 true,mk_dir failed with dir already exists 错误。

Web 服务器是 apache2。

无法解释这种行为。

【问题讨论】:

  • 坦率地说,我不知道你的问题是什么,但要点让我觉得你被统计缓存抓住了? php.net/manual/en/function.clearstatcache.php
  • 这在我看来像是一个 XY 问题:为什么你认为你需要在 PHP 中模拟互斥锁?请求周期就是这样,PHP 是无状态的,2 个并发请求实际上并不共享状态(就您编写的 PHP 代码而言)。互斥锁的存在是为了防止竞争条件和对多个线程共享的内存(状态)的并发访问。除非您尝试做一些非常奇怪的事情,否则 PHP 根本不需要它们,这就是 PHP 没有内置功能的原因
  • @JonStirling:您可能说得对,可以通过解释 PHP 如何在内部处理实际 IO 操作(缓冲 IO 和缓存系统调用)来回答 OP 的问题。但是,我认为 OP 应该问的真正问题是 为什么 他试图在 PHP 中创建目录作为某种互斥系统
  • @Ootegem 脚本作为缓存工作,我们调用 Web 服务器来获取文件并避免每次缓存文件时调用该站点。每小时它都会将最新版本与新版本进行比较,并在修改后更改它,并为调用者提供本地文件。因此,每次脚本需要文件时都不会调用缓存服务器。今天服务器停止响应,因此在每次调用时,由于超时延迟,脚本都会搜索创建大量 tcp 调用的新文件。因此,当一个脚本尝试访问文件服务器时,我试图阻止后续调用。
  • @Régis:所以它是一种缓存机制,而不是互斥体。请不要称它为互斥体,因为这让我想到了各种可怕的事情......

标签: php


【解决方案1】:

当您使用 stat()、lstat() 或受影响函数列表(如下)中列出的任何其他函数时,PHP 会缓存这些函数返回的信息以提供更快的性能。但是,在某些情况下,您可能需要清除缓存的信息。例如,如果在一个脚本中多次检查同一个文件,并且该文件在该脚本的操作期间有被删除或更改的危险,您可以选择清除状态缓存。在这些情况下,您可以使用 clearstatcache() 函数来清除 PHP 缓存的有关文件的信息。

此函数缓存有关特定文件名的信息,因此如果您对同一文件名执行多个操作并且需要不缓存有关该特定文件的信息,则只需调用 clearstatcache()。

受影响的函数包括 stat()、lstat()、file_exists()、is_writable()、is_readable()、is_executable()、is_file()、is_dir()、is_link()、filectime()、fileatime()、 filemtime()、fileinode()、filegroup()、fileowner()、filesize()、filetype() 和 fileperms()。

TLDR,添加 clearstatcache();在任何检查之前

来源:http://php.net/manual/en/function.clearstatcache.php

【讨论】:

  • BUSTED!.. 我正在查看我的本地 php.chm 帮助文件,并意识到我基本上是在改写我在那里读到的内容,所以我复制了它。我已经添加了来源。希望这足以让我远离狗屋
  • 只是为了实践我所宣扬的:根据PHP licensing page,该手册是在知识共享署名3.0许可下获得许可的,归结为this:如果您提供,则允许重新分发“适当的信用”,提供“许可证链接”和“说明是否进行了更改”。后一种意思:使用[...]之类的东西来表示你已经省略了一些东西,或者添加一个脚注,说明你已经添加了一些格式以使某些相关部分更加突出
  • 我并不是在暗示你有恶意,而是刚刚“把书扔给你”_,并且刚刚阅读了 CCA3 许可证:从技术上讲,你似乎也应该包含许可证
【解决方案2】:

您可能想解释得更好,并粘贴更好的代码示例...

同时,这是处理 mkdir/rmdir 的更好方法

$mydir= 'my/dir/'

if(!is_dir($myDir)) {
    mkdir($myDir, 0755, true);
    wait(30);
    rmdir(mydir);
}

您可能需要了解如何递归删除目录和文件,这可能会有所帮助... ;)

另外,wait()是你制作的 PHP 函数吗?! 我知道sleep() 但不知道wait()...

【讨论】:

  • 我的错,忘记编辑那部分代码...刚刚修复它... ;)
【解决方案3】:

代码可以更漂亮、更真实,只是力求简洁。补充一下apc或者xcode缓存问题...

在互联网上徘徊以寻求提示,我读到当在两个选项卡上调用相同的脚本时,firefox 非常聪明(f...他),它等待第一个完成后再执行第二个。

为每个调用添加不同的参数(?t=1 和 ?t=2)或使用 chrome 进行一次调用并使用 ff 进行另一次调用,使其完美运行......真是浪费时间......

【讨论】:

  • 欢迎来到 SO。请拨打the tour,并通读帮助中心。发布“谢谢”作为评论或答案实际上是非常不鼓励的。这根本不是答案。相反,系统会要求您通过投票来标记有用的答案(单击每个答案左上角、得分上方的灰色箭头),和/或将解决问题的答案标记为已接受(通过单击大的、每个答案旁边的空心 V 符号)。接受一个答案会给你+2声望,作为一种鼓励。完成此操作后,您也应该删除此非答案
  • 另请注意,不鼓励以问候语或诸如 “提前感谢” 之类的短语来结束问题或回答。一个很好的问题详细说明了您要完成的工作,重现的最小代码示例,并解释了您为解决问题所采取的步骤。而已。签名被认为是“噪音”。答案也是如此。请避免添加诸如“问候”之类的内容,即使这样做看起来很礼貌:-P
猜你喜欢
  • 2013-05-26
  • 1970-01-01
  • 1970-01-01
  • 2016-12-14
  • 2020-01-23
  • 1970-01-01
  • 2020-11-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多