Rich
Rich

Reputation: 15464

how to synchronise multiple processes in PHP to simulate wait()/notifyAll()

I'm trying to test a race condition in PHP. I'd like to have N PHP processes get ready to do something, then block. When I say "go", they should all execute the action at the same time. Hopefully this will demonstrate the race.

In Java, I would use Object.wait() and Object.notifyAll(). What can I use in PHP?

(Either Windows or linux native answers are acceptable)

Upvotes: 1

Views: 485

Answers (3)

Tomáš Zato
Tomáš Zato

Reputation: 53307

Usually with PHP file lock approach is used. One create a RUN_LOCK or similar file and asks for file_exists("RUN_LOCK"). This system is also used to secure potential endless loops in recursive threads.

I decided to require the file for the execution. Other approach may be, that existence of the file invokes the blocking algorithm. That depends on your situation. Always the safer situation should be the easier to achieve.

Wait code:

/*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);

I guess it would be nice to have a blocking function for that, like this one:

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
}

It implements timeout. You don't need them but maybe someone else will.
Usage:

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";
}

This will output:

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!

Upvotes: 1

Rich
Rich

Reputation: 15464

  • Create a file "wait.txt"
  • Start N processes, each with the code shown below
  • Delete the "wait.txt" file.

...

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

Upvotes: 2

Artjom Kurapov
Artjom Kurapov

Reputation: 6155

PHP doesn't have multithreading. And its not planned to be implemented either. You can try hacks with sockets though or 0MQ to communicate between multiple processes

See Why does PHP not support multithreading? Php multithread

Upvotes: -1

Related Questions