gpt4 book ai didi

php - 我的并发编程逻辑有什么问题吗?

转载 作者:行者123 更新时间:2023-12-03 12:49:31 24 4
gpt4 key购买 nike

我同时编写了一个网络蜘蛛来蜘蛛页面。对于蜘蛛找到的每个链接,我想 fork 一个新的子链接,重新开始该过程。

我不想使目标服务器过载,因此我创建了一个所有对象都可以访问的静态数组。每个子进程都可以将自己的 PID 添加到数组中,父进程或子进程都应检查数组以查看是否满足 $maxChildren 要求,如果满足,请耐心等待任何子进程完成。

如您所见,我将 $maxChildren 设置为 3。我希望在任何给定时间看到 3 个并发进程。然而,事实并非如此。 linux top 命令在任何给定时间显示 12 到 30 个进程。在并发编程中,如何调节同时进程的数量?我的逻辑目前受到 Apache 如何处理其最大子级的启发,但我不太确定它是如何工作的。

正如其中一个答案所指出的,全局访问静态变量会带来竞争条件问题。为了解决这个问题, $children 数组将进程的唯一 $PID 作为键和值,从而创建一个唯一的值。我的想法是,由于任何对象只能处理一个 $children[$pid] 值,因此不需要锁定。这不是真的吗?两个进程是否有可能在某个时刻尝试取消设置或添加相同的值?

private static $children = array();

private $maxChildren = 3;

public function concurrentSpider($url) {

// STEP 1:
// Download the $url
$pageData = http_get($url, $ref = '');

if (!$this->checkIfSaved($url)) {
$this->save_link_to_db($url, $pageData);
}

// STEP 2:
// extract all hyperlinks from this url's page data
$linksOnThisPage = $this->harvest_links($url, $pageData);

// STEP 3:
// Check the links array from STEP 2 to see if this page has
// already been saved or is excluded because of any other
// logic from the excluded_link() function
$filteredLinks = $this->filterLinks($linksOnThisPage);

shuffle($filteredLinks);

// STEP 4: loop through each of the links and
// repeat the process
foreach ($filteredLinks as $filteredLink) {

$pid = pcntl_fork();
switch ($pid) {
case -1:
print "Could not fork!\n";
exit(1);
case 0:
if ($this->checkIfSaved($filteredLink)) {
exit();
}
//$pid = getmypid();
print "In child with PID: " . getmypid() . " processing $filteredLink \n";


$var[$pid]->concurrentSpider($filteredLink);
sleep(2);

exit(1);
default:
// Add an element to the children array
self::$children[$pid] = $pid;
// If the maximum number of children has been
// achieved, wait until one or more return
// before continuing.

while (count(self::$children) >= $this->maxChildren) {
//print count(self::$children) . " children \n";
$pid = pcntl_waitpid(-1, $status);
unset(self::$children[$pid]);
}
}
}
}

这是用 PHP 编写的。我知道参数为 -1 的 pcntl_waitpid 函数会等待任何子进程完成,而不管父进程 ( http://php.net/manual/en/function.pcntl-waitpid.php )。

我的逻辑有什么问题,如何纠正它以便只有 $maxChildren 进程同时运行?如果您有建议,我也愿意改进总体逻辑。

最佳答案

首先要注意的是:如果这确实是多个线程之间共享的全局变量,则有可能多个线程同时向其中添加内容,并且您会遇到竞争条件。您需要某种并发控制来确保只有一个进程同时访问您的全局数组。

此外,尝试简单的调试技巧,即每次 fork 新蜘蛛时,让每个进程写出(到控制台或文件)其 PID 和全局数组的完整内容。它将帮助您检查您的假设(在某些时候显然是错误的)并找出问题所在。

编辑:(回应评论)

我不是 PHP 开发人员,但如果我不得不猜测,基于您正在使用计算操作系统级进程的操作系统工具这一事实,我猜测您的 fork 正在生成多个进程,但是您的静态数组是当前进程内的全局数组。实现系统范围的共享内存要复杂得多!

如果您只是想计算某些内容并确保共享资源的实例不会失控,请查看 semaphores ,并看看您是否可以在 PHP 中找到一种方法来创建可以在蜘蛛的多个实例之间共享的命名信号量对象。

关于php - 我的并发编程逻辑有什么问题吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16952293/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com