我试图创建使用共享块内存的计数器,只需查看代码:
$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
我想在多线程中为文件中的读写字符串创建此类。
答案 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
}
}
}