Вам необходимо использовать:
use warnings;
use strict;
Это скажет вам, что вы используете глобальные переменные $ i и $ j в подпрограмме. Так как у вас есть несколько потоков, обращающихся к переменным, все чертовы рвутся. Кроме того, все они тоже используют один файл - еще один источник проблем. И вы поняли, что у вас есть и скалярный '$ threads', и массив '@threads'?
С потоками глобальные переменные ... ну, если не враг, очень проблематичны.
Избегайте использования формы ФАЙЛОВ open
; используйте 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
.