PHP共享块内存和fork

时间:2011-04-06 21:31:58

标签: php multithreading fork

我试图创建使用共享块内存的计数器,只需查看代码:

    $i=0; $counter = new counter('g');
while($i<3){
  $pid = pcntl_fork();
  echo $counter->get()."\t".$i."\t".$pid."\n";
  $i++;
}

class counter {
  protected static $projID = array();
  protected $t_key;
  protected $length;

  function __construct($projID){
    !in_array( $projID, self::$projID) or die('Using duplicate project identifer "'.$projID.'" for creating counter');
    self::$projID[] = $projID;
    $this->t_key = ftok(__FILE__, $projID);
    $this->shmid = shmop_open($t_key, 'c', 0755, 64);
    $this->length = shmop_write($this->shmid, 0, 0);
    shmop_close($this->shmid);
  }

  function get(){
    $sem = sem_get($this->t_key, 1);
    sem_acquire($sem);
      $shmid = shmop_open($this->t_key, 'c', 0755, 64);
      $inc = shmop_read($shmid, 0, $this->length);
      $this->length = shmop_write($shmid, $inc+1, 0);
      shmop_close($shmid);
    sem_release($sem);
    return $inc;
  }
}

但是我得到了奇怪的结果

7   0   2567
8   1   2568
9   0   0
1   1   0
2   2   2569
40  1   2570
4   2   2572
3   2   0
51  2   2571
52  1   0
63  2   0
5   2   0
64  2   2573
65  2   0

我想在多线程中为文件中的读写字符串创建此类。

2 个答案:

答案 0 :(得分:1)

致电pcntl_fork后,您没有处理PID。你的forks正在分叉,因为循环继续执行并且fork。

除非您尝试创建本地化的fork炸弹,否则可能不希望您的叉子分叉。

我在本地做了一些工作,试图弄清楚是否只能解决问题,但事实并非如此。它几乎看起来没有正确写入共享内存段,就好像字符串两侧的一个数字正在重复,这会破坏所有数字并迫使事情重新开始。

完全猜测。

您可能想要考虑使用PHP执行并行处理的另一种方法。使用Gearman作为多进程工作队列是我最喜欢的解决方案。

答案 1 :(得分:1)

你根本没有结束子进程,它们永远不会完成。您也没有检查过程是否正确分叉,无法控制已完成的处理以及处理顺序。分叉进程并不是其他语言提供的多线程,所有发生的事情都是当前进程被复制并且变量被共享 - 你的$ i不会以3结束,也不保证哪个进程首先完成或者最后。

尝试:

while($i < 3)
{
    $pid = pcntl_fork();

    if($pid == -1)
    {
        // some sort of message that the process wasn't forked 
        exit(1);
    }
    else
    {
        if($pid)
        {
            pcntl_wait($status); // refer to PHP manual to check what this function does
        }
        else
        {
            // enter your code here, for whatever you want to be done in parallel
            // bear in mind that some processes can finish sooner, some can finish later
            // good use is when you have tasks dependent on network latency and you want
            // them executed asynchronously (such as uploading multiple files to an ftp or 
            // synchronizing of something that's being done over network

            // after you're done, kill the process so it doesn't become a zombie

            posix_kill(getmypid(), 9); // not the most elegant solution, and can fail
        }
    }
}