免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: Perl_Er
打印 上一主题 下一主题

关于perl的多线程&多进程的问题 [复制链接]

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
31 [报告]
发表于 2009-07-01 17:46 |只看该作者
原帖由 Perl_Er 于 2009-7-1 16:26 发表
改成这个样子是可以的,每次起10个thread,但是每次都要等这10个完成才能起下一轮的10个,有没有更好的办法了。

问题就出在这里

  1.                 foreach my $t (keys %thrs){
  2.                                 $thrs{$t}->join();
  3.                                 delete $thrs{$t};
  4.                 }
复制代码

在 join 之前,你应该先用 is_joinable 判断下是否能 join,不能的就忽略。另外,也可以考虑直接用 threads->list(threads::joinable) 获取可以 join 的线程的列表,不过这个功能 Perl 5.8.8 没有,Perl 5.10.0 新增加的。

另外如果每次起得太多,对performance影响会比较大,如何确定同时起多少个比较合适. 谢谢!

这个要你自己估计了。

论坛徽章:
0
32 [报告]
发表于 2009-07-01 18:00 |只看该作者

回复 #31 MMMIX 的帖子

对的,以前也是这么设计的,但是得到这个错误:Can't locate object method "is_joinable" via package "threads" at thread1.pl.bak line 23.
perl的版本是,
bash-3.2# perl -v

This is perl, v5.8.8 built for PA-RISC1.1-thread-multi
(with 26 registered patches, see perl -V for more detail)

Copyright 1987-2006, Larry Wall

Binary build 817 [257965] provided by ActiveState http://www.ActiveState.com
Built Mar 20 2006 19:44:08

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.




#!/usr/bin/perl
use threads;
use strict;
use Data:umper;

sub prt(){
        `echo "$_[0]" >> t.txt`;
}


my $current_thread;
my %thrs = ();
for(1..300)
{
         $current_thread = scalar (keys %thrs);
         if( $current_thread < 10 )
         {
                $thrs{$_} = threads->create(\&prt,$_);
         }else{
                print "more than 10 threads\n";
                print Dumper \%thrs;
                foreach my $t (keys %thrs){
                        if($thrs{$t}->is_joinable()){
                                $thrs{$t}->join();
                                delete $thrs{$t};
                        }
                }
                $thrs{$_} = threads->create(\&prt,$_);
         }
}
foreach my $t (keys %thrs){
        $thrs{$t}->join();
        delete $thrs{$t};
}

print Dumper \%thrs;

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
33 [报告]
发表于 2009-07-01 18:13 |只看该作者
原帖由 Perl_Er 于 2009-7-1 18:00 发表
对的,以前也是这么设计的,但是得到这个错误:Can't locate object method "is_joinable" via package "threads" at thread1.pl.bak line 23.
perl的版本是,
bash-3.2# perl -v

This is perl, v5.8.8 bu ...

Perl 5.8.8 是没有 is_joinable 的。不过你可以用父子线程共享的线程个数计数器来控制子线程数量,然后在线程创建后,将其 detach 掉。

或者,你也可以将 Perl 升级到 5.10.0

[ 本帖最后由 MMMIX 于 2009-7-1 18:14 编辑 ]

论坛徽章:
0
34 [报告]
发表于 2009-07-01 19:28 |只看该作者

回复 #33 MMMIX 的帖子

这样好像不行了,好像是加锁的原因,帮忙看看怎么处理?
#!/usr/bin/perl
use threads;
use threads::shared;
use strict;

my $thread_count :shared = 0;

sub prt(){
        lock($thread_count);
        $thread_count++;
        print "the thread is $_[0]\n";
        sleep 1;
        $thread_count--;
}


for(1..30000)
{
        if( $thread_count < 20 )
        {
                if(my $t = threads->create(\&prt,$_)){
                        $t->detach();
                }
        }else{
                print "more than 10 threads\n";
                if(my $tt= threads->create(\&prt,$_)){
                        $tt->detach();
                }
        }
}

[ 本帖最后由 Perl_Er 于 2009-7-1 19:33 编辑 ]

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
35 [报告]
发表于 2009-07-01 20:56 |只看该作者
原帖由 Perl_Er 于 2009-7-1 19:28 发表
这样好像不行了,好像是加锁的原因,帮忙看看怎么处理?

这是我写的:

  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;

  4. use threads;
  5. use threads::shared;

  6. my $thread_num :shared = 0;

  7. sub start_thread {
  8.         print "Thread ", threads->tid(), " started, current thread numbers $_[0]\n";
  9.         {
  10.                 lock($thread_num);
  11.                 $thread_num--;

  12.                 cond_signal($thread_num);
  13.         }
  14. }

  15. for (1 .. 200) {
  16.         {
  17.                 lock($thread_num);
  18.                 cond_wait($thread_num) until $thread_num < 10;

  19.                 my $t = threads->create(\&start_thread, $thread_num + 1);
  20.                 $t->detach();
  21.                
  22.                 $thread_num++;
  23.         }
  24. }
复制代码


很奇怪的是,启动的线程的总数并不是 200 个。

使用 is_joinable 的例子:

  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;

  4. use threads;

  5. my $thread_num = 0;

  6. sub start_thread {
  7.         print "Thread ", threads->tid(), " started, current thread number $_[0]\n";
  8. }

  9. for (1 .. 200) {
  10.         if ($thread_num >= 10) {
  11.                 for my $t (threads->list(threads::joinable)) {
  12.                         $t->join();
  13.                         $thread_num--;
  14.                 }
  15.                 redo;
  16.         }

  17.         threads->create(\&start_thread, $thread_num + 1);
  18.         $thread_num++;
  19. }

  20. for my $t (threads->list()) {
  21.         $t->join();
  22. }
复制代码

[ 本帖最后由 MMMIX 于 2009-7-1 21:09 编辑 ]

论坛徽章:
0
36 [报告]
发表于 2009-07-01 21:16 |只看该作者

回复 #35 MMMIX 的帖子

我这样可以,你的那个is_joinable的可以吗?
  1. #!/usr/bin/perl
  2. use threads;
  3. use threads::shared;
  4. use strict;

  5. my $thread_count :shared = 0;

  6. sub prt(){

  7.     $thread_count++;
  8.     print "the thread is $_[0]\n";
  9.     sleep 5;
  10. #    print "the count is :$thread_count","\n";
  11.     $thread_count--;
  12. }


  13. for(1..101)
  14. {
  15.     if( $thread_count < 10 )
  16.     {
  17.         if(my $t = threads->create(\&prt,$_)){
  18.             $t->detach();
  19.         }
  20.     }else{
  21.         sleep 1;
  22.         print "more than 100 threads\n";
  23.         redo;
  24.     }
  25. }
复制代码

[ 本帖最后由 Perl_Er 于 2009-7-1 21:19 编辑 ]

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
37 [报告]
发表于 2009-07-01 21:19 |只看该作者
原帖由 Perl_Er 于 2009-7-1 21:16 发表
我这样可以,

可以什么?

BTW,用 sleep 同步线程/进程是不可靠的。

论坛徽章:
0
38 [报告]
发表于 2009-07-01 21:20 |只看该作者

回复 #37 MMMIX 的帖子

就是说我的这个程序运行后是101个线程,去掉sleep也是可以的

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
39 [报告]
发表于 2009-07-01 21:29 |只看该作者
原帖由 Perl_Er 于 2009-7-1 21:20 发表
就是说我的这个程序运行后是101个线程,去掉sleep也是可以的

但你那个是不正确的,对共享资源的访问应该加锁。

我把你那个去掉 sleep 运行了多次,结果各次创建的子线程的总数并不相同。

[ 本帖最后由 MMMIX 于 2009-7-1 21:34 编辑 ]

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
40 [报告]
发表于 2009-07-01 21:30 |只看该作者
原帖由 Perl_Er 于 2009-7-1 21:16 发表
你的那个is_joinable的可以吗?

那个没有问题。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP