【问题标题】:Creating a directory from multiple threads从多个线程创建目录
【发布时间】:2021-12-07 03:00:13
【问题描述】:

如果多个线程执行以下操作:

if ( !is_dir($dir) )
    mkdir($dir, 0, true);

如果两个线程“同时”检测到目录不存在,然后他们都尝试创建它,会发生什么?

mkdir 是否同步以防止坏事发生,或者有没有办法 flock 确保只有一个线程创建目录和/或文件?

【问题讨论】:

  • 您是否将您的 php 警告转换为异常?我可以看到的其他选项是:@(哦,天哪,我不敢相信我提出了这个建议)或与flock 的一些自定义同步点
  • 您的检测目录丢失的方法必须以这种方式同步,只有一个线程来执行。一个相关的问题是什么表明群是同步的stackoverflow.com/questions/185203/…

标签: php


【解决方案1】:

我知道这是一个老问题,但如果你有一个将错误转换为异常的错误处理程序(无论如何这都是个好主意),这样的事情真的很有效:

    /**
     * Create a folder in a thread safe way
     * Between 'is_dir' and 'mkdir' another thread could have created a folder. 
     * This can cause the system to raise an unwarrented error
     * 
     * Returns TRUE if folder was created, NULL if folder already exists
     * 
     * Throws exception on any other error
     *
     * @param  array   $array
     * @param  string  $key
     * @param  mixed   $value
     * @return array
     */
    function mkdir_thread_safe($dir, $permissions = 0777, $recursive = false)
    {   
        if(is_dir($dir)) return;

        try {
             mkdir($dir, $permissions, $recursive);
        }
        catch (\ErrorException $e){

            if(is_dir($dir)) return;

            throw $e;
        }

        return true;
    }

这是异常转换处理程序的错误 - 无论如何,这确实是一个很好的做法,应该在任何应用程序入口点的开头添加。一些现代框架,如 laravel,默认会处理这个问题,所以如果你使用 laravel,你的错误已经被转换为异常。

set_error_handler(function ($level, $message, $file, $line, $context)
{
    if (error_reporting() & $level)
    {
        throw new ErrorException($message, $level, 0, $file, $line);
    }
});

【讨论】:

    【解决方案2】:

    其中只有一个会设法创建目录,另一个 mkdir 将返回 false 并发出警告

    你也可以看看这个bug在php中,和你的问题不完全一样,但它是相关的

    【讨论】:

    • 另一个也会抛出警告
    • 那么……怎么样? :) zerkms,你 100% 确定这会发生吗?如果是这样,那么解决方案是什么?
    • @zerkms 是的,它会发出警告,谢谢,我将它添加到我的答案中。 @AndreiBogdan,它仍然可以工作,但如果你想摆脱警告,你可以用@ 抑制它,就像@zerkms 建议的那样
    猜你喜欢
    • 2017-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多