I'm writing a script that needs to execute concurrent tasks in PHP.
I ran a little test and ran into strange result. I'm using pcntl_fork to generate a child. The parent process does nothing but wait for the child to complete.
I'm generating 5 children, each child runs a function that generates a random number (of seconds) and sleeps for that long. For some reason - all children generate the same number.
Here's a code example:
private $_child_count = 0;
private function _fork_and_exec($func)
{
$cid = ++$this->_child_count;
$pid = pcntl_fork();
if ($pid){ // parent
return $pid;
} else { // child
$func($cid);
//pcntl_waitpid(-1, $status);
exit;
}
}
public function parallel_test()
{
$func = function($id){
echo 'child ' . $id . ' starts'."\n";
$wait_time = mt_rand(1,4);
echo 'sleeping for '.$wait_time."\n";
sleep($wait_time);
echo 'child ' . $id . ' ends'."\n";
};
$children = [];
for ($i=0; $i<5; $i++){
$children[] = $this->_fork_and_exec($func) ."\n";
}
pcntl_wait($status);
echo 'done' ."\n";
exit;
}
Example output:
child 1 starts
sleeping for 1
child 2 starts
sleeping for 1
child 3 starts
sleeping for 1
child 4 starts
sleeping for 1
child 5 starts
sleeping for 1
child 1 ends
child 2 ends
child 3 ends
child 4 ends
child 5 ends
done
thanks in advance
I really think you should look at
pthreads
which provides multi-threading that is compatible with PHP based on Posix Threads.Simple as
Output
That is because all children start with the same state (fork() duplicates the code and data segments). And since rand and mt_rand are pseudorandom generators, they will all generate the same sequence.
You will have to re-initialize the random generator, for example with the process/thread ID or read a few bytes from /dev/urandom.