2

有人可以建议我为什么在下面的代码中打开文件时出错。这些错误从 25 个线程的第 9 次迭代大约一半开始,并且是“打开的文件太多”错误。该错误仅在线程中运行时发生,并且仅在使用 DBI 连接/断开连接时发生。这根本不应该影响打开的文件计数吗?我对 Perl 还很陌生,所以不确定我是否做了一些奇怪的事情。这是在 Perl 5.8.8 上。在 Solaris 10 上。

use threads ();
use DBI;
use DBD::Oracle;

my $thrds=25;
my $iter=10;
my @threads;

for (my $j=0; $j<$iter; $j++) {
    &start($j);
}

sub start {
    my $k=$_[0];
    for (my $i=0; $i<$thrds; $i++) {
        $threads[$i] = threads->new(\&RunThread,$k, $i);
    }
    for (my $i=0; $i<$thrds; $i++) { $threads[$i]->join; }
}

sub RunThread {
    my $dbh = DBI->connect("dbi:Oracle:lnrmsd9.world", "rms_reader", "rms_reader") or die "failed connect";
    my ($x, $y)=@_;
    open (my $fh, ">/tmp/da") or die "failed $! at iter $x thread $y";
    close ($fh);
    $dbh->disconnect;
}
4

2 回答 2

5

你需要使用:

use warnings;
use strict;

这些会告诉您您在子例程中使用全局变量 $i 和 $j。由于您有多个线程访问变量,所有地狱都崩溃了。此外,它们也都共享一个文件 - 另一个麻烦来源。您是否意识到您同时拥有一个标量“$threads”和一个数组“@threads”?

对于线程,全局变量是……好吧,如果不完全是敌人,也是非常有问题的。

open避免使用;的 FILE 句柄形式 使用my更自由。

而且你不需要说'使用 DBD::Oracle;' 曾经。您有时可能需要使用变体:

use DBD::Oracle qw( :ora_types );

访问特定于 Oracle 的数据类型。


未经测试的修订:

use strict;
use warnings;
use threads ();
use DBI;
use DBD::Oracle;

my $threads=25;
my $iter=10;

for ($j = 0; $j < $iter; $j++) {
    &start($j);
}

sub start {
    my($j) = @_;
    my(@threads);
    for (my $i = 0; $i < $threads; $i++) {
        $threads[$i] = threads->new(\&RunThread,$j, $i);
    }
    for ($i=0; $i < $threads; $i++) { $threads[$i]->join; }
}

sub RunThread {
    my $dbh = DBI->connect("dbi:Oracle:ora", "user", "pass") or die "failed connect";
    my($j, $i) = @_;
    open(my $fh, ">/tmp/da") or die "failed $! at iter $j thread $i";
    close $fh;
    $dbh->disconnect;
}

我不明白的一件事 - 为什么我不应该使用use DBD::Oracle;

如果您查看“perldoc DBD::Oracle”,您将看到概要:

use DBI;

$dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd);

因此,DBD::Oracle 模块的主要文档表明您不直接使用它。

使用它没有害处;没有必要使用它。DBI 模块自动加载调用中的连接字符串隐含的驱动程序DBI->connect()。通过编写use DBD::Oracle;,您可以使 DBI 不必实际进行加载(它已经完成)。我想您还可以让 Perl 验证该模块是否可以与该use子句一起加载。

于 2010-06-22T14:59:38.187 回答
1

尝试

my $FILE;
open ($FILE, ">/tmp/da") or die "failed $! at iter $j thread $i";
close ($FILE);

这是最佳实践。

于 2010-06-22T15:06:46.123 回答