2013-04-17 2 views
1

Я пытаюсь проверить состояние гонки на PHP. Я хотел бы, чтобы N процессов PHP готовились что-то сделать, а затем блокировать. Когда я говорю «идти», они должны все выполнить действие в одно и то же время. Надеюсь, это продемонстрирует гонку.как синхронизировать несколько процессов в PHP для имитации wait()/notifyAll()

В Java я бы использовал Object.wait() и Object.notifyAll(). Что я могу использовать в PHP?

(родные ответы либо Windows или Linux являются приемлемыми)

+0

Я хотел бы использовать файл и проверить 'file_exists'. Здесь он действительно разлагает то, что означает «то же время». –

+0

«в то же время» означает параллельно и все начинаются как можно ближе к одному и тому же моменту. Когда вы говорите «check file_exists», вы имеете в виду со спин-блокировкой? Это может сработать. – Rich

+0

Да, что-то с функцией '' usleep' '(http://cz2.php.net/manual/en/function.usleep.php). –

ответ

2
  • Создать файл «wait.txt»
  • Start N процессов, каждый из которых код, показанный ниже
  • Удалить файл "wait.txt".

...

<?php 
while (file_exists('wait.txt')) {} 
runRaceTest(); 
+0

Мне нравится ваш ответ, но, конечно, я не откажусь от какой-то дополнительной репутации :) –

-1

PHP не имеет многопоточность. И его также не планируется реализовать. Вы можете попробовать хаки с гнездами, хотя и 0MQ для обмена данными между несколькими процессами

См Why does PHP not support multithreading? Php multithread

+0

Я знаю; поэтому я написал «процессы» вместо «threads» – Rich

+1

очень устаревшая информация там, кстати ... http://php.net/Thread –

1

Обычно используется с PHP блокировка файла подход. Один создает файл RUN_LOCK или аналогичный файл и запрашивает file_exists("RUN_LOCK"). Эта система также используется для защиты потенциальных бесконечных циклов в рекурсивных потоках.

Я решил потребовать файла для выполнения. Другим подходом может быть то, что существование файла вызывает алгоритм блокировки. Это зависит от вашей ситуации. Всегда более безопасная ситуация должна быть легче достичь.

код Wait:

/*prepare the program*/ 
    /* ... */ 
/*Block until its time to go*/ 
define("LOCK_FILE", "RUN_UNLOCK"); //I'd define this in some config.php 
while(!file_exists(LOCK_FILE)) { 
    usleep(1); //No sleep will eat lots of CPU 
} 
/*Execute the main code*/ 
    /* ... */ 
/*Delete the "run" file, so that no further executions should be allowed*/ 
usleep(1); //Just for sure - we want other processes to start execution phase too 
if(file_exists(LOCK_FILE)) 
    unlink(LOCK_FILE); 

Я думаю, было бы неплохо иметь функцию блокировки для этого, как этот:

function wait_for_file($filename, $timeout = -1) { 
    if($timeout>=0) { 
     $start = microtime(true)*1000; //Remember the start time 
    }  
    while(!file_exists($filename)) {  //Check the file existence 
     if($timeout>=0) {     //Only calculate when timeout is set 
      if((microtime(true)*1000-$start)>$timeout) //Compare current time with start time (current always will be > than start) 
      return false;   //Return failure 
     } 
     usleep(1);   //Save some CPU 
    } 
    return true;   //Return success 
} 

Он реализует тайм-аут. Вы им не нужны, но, может быть, кто-то другой.
Использование:

header("Content-Type: text/plain; charset=utf-8"); 
ob_implicit_flush(true);while (@ob_end_clean()); //Flush buffers so the output will be live stream 
define("LOCK_FILE","RUN_FOREST_RUN"); //Define lock file name again 
echo "Starting the blocking algorithm. Waiting for file: ".LOCK_FILE."\n"; 
if(wait_for_file(LOCK_FILE, 10000)) { //Wait for 10 secconds 
    echo "File found and deleted!\n"; 
    if(file_exists(LOCK_FILE)) //May have been deleted by other proceses 
     unlink(LOCK_FILE); 
} 
else { 
    echo "Wait failed!\n"; 
} 

Это Выведет:

Starting the blocking algorithm. Waiting for file: RUN_FOREST_RUN 
Wait failed! 

~or~ 

Starting the blocking algorithm. Waiting for file: RUN_FOREST_RUN 
File found and deleted! 
+0

Спасибо. Я думаю, что добавление «usleep» в цикл ожидания приведет к тому, что потоки будут менее жестко синхронизированы, поэтому я предпочитаю версию без нее. Этот подход file_exists неэффективен, но эффективен, как и остальная часть PHP ;-) – Rich

+0

Одна микросекунда - очень короткий промежуток времени. Что именно эти потоки должны делать? –

+0

В моем случае они предназначены для участия в довольно стандартном режиме чтения-записи, как показано на примере [по википедии] (http://en.wikipedia.org/wiki/Race_condition#Example). Для настройки тестового примера мы не заботимся о том, чтобы сжечь некоторый процессор в тестовых процессах, но мы заботимся о том, чтобы все процессы выполнялись в состоянии «запуска» в тот же момент. Вызов «usleep» здесь означает, что процесс прерывается O/S и отвлекает код, поэтому я считаю, что использовать его здесь некорректно. – Rich

Смежные вопросы