我正在编写一个需要在PHP中执行并发任务的脚本。
我跑了一点测试并遇到了奇怪的结果。我使用pcntl_fork生成一个孩子。父进程只会等待孩子完成。
我生成了5个孩子,每个孩子都会运行一个生成随机数(秒)并且长时间睡眠的功能。出于某种原因 - 所有孩子都生成相同的数字。
这是一个代码示例:
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;
}
示例输出:
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
提前致谢
答案 0 :(得分:5)
这是因为所有子节点都以相同的状态开始(fork()复制代码和数据段)。由于rand和mt_rand是pseudorandom生成器,它们都将生成相同的序列。
您必须重新初始化随机生成器,例如使用进程/线程ID或从/ dev / urandom读取几个字节。
答案 1 :(得分:1)
我真的认为你应该看看pthreads
,它提供了与基于Posix线程的PHP兼容的多线程。
简单如
class AsyncOperation extends Thread {
public function __construct($arg) {
$this->arg = $arg;
}
public function run() {
if ($this->arg) {
echo 'child ' . $this->arg . ' starts' . "\n";
$wait_time = mt_rand(1, 4);
echo 'sleeping for ' . $wait_time . "\n";
sleep($wait_time);
echo 'child ' . $this->arg . ' ends' . "\n";
}
}
}
$t = microtime(true);
$g = array();
foreach(range("A","D") as $i) {
$g[] = new AsyncOperation($i);
}
foreach ( $g as $t ) {
$t->start();
}
输出
child B starts
sleeping for 3
child B ends
child C starts
sleeping for 3
child C ends
child A starts
sleeping for 4
child A ends
child D starts
sleeping for 4
child D ends