2013-03-12 5 views
3

Если несколько потоков сделать следующее:Создание каталога из нескольких потоков

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

что произойдет, если два потока будет обнаруживать «одновременно», что каталог не существует, а затем они оба пытаются и создать Это?

Is mkdir синхронизирован, чтобы предотвратить возникновение плохих событий или существует способ для flock, чтобы убедиться, что только один поток создает каталог и/или файлы?

+1

Вы преобразовываете свои предупреждения php в исключения? Другие параметры, которые я мог видеть, это: '@' (о боже, я не могу поверить, что я предлагаю это) или какую-то пользовательскую точку синхронизации с 'flock' – zerkms

+0

Ваш метод, который обнаруживает недостающую директорию, должен быть синхронизирован таким образом, что только один поток выполнить это. Связанный с нами вопрос, что показывает, что стая синхронизирована, - это http://stackoverflow.com/questions/185203/php-5-x-syncronized-file-access-no-database, что вы – user1929959

ответ

1

Только один из них удастся создать каталог, другой mkdir вернется false и бросить предупреждение

Вы также можете посмотреть на этой bug в PHP, это не совсем так, как с вашим вопросом , но это связано

+0

Другой также выдаст предупреждение – zerkms

+0

So ... как оно ? :) zerkms, вы на 100% уверены, что это произойдет? Если да, то каким было бы решение? – AndreiBogdan

+1

@zerkms да, это бросит предупреждение, спасибо, я добавил его к моему ответу. @AndreiBogdan, он все равно будет работать, но если вы хотите избавиться от предупреждения, вы можете его подавить с помощью '@', как предлагалось @zerkms –

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); 
    } 
}); 
Смежные вопросы