4

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

前もって感謝します

4

2 に答える 2

6

これは、すべての子が同じ状態で始まるためです(fork()はコードとデータセグメントを複製します)。また、randとmt_randは疑似ランダムジェネレーターであるため、すべて同じシーケンスを生成します。

たとえば、プロセス/スレッドIDを使用してランダムジェネレーターを再初期化するか、/ dev/urandomから数バイトを読み取る必要があります。

于 2013-02-14T16:17:14.837 に答える
1

pthreadsPosixスレッドに基づく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
于 2013-02-14T16:31:05.230 に答える