perl多线程

perl多线程

在大骆驼书里有这么一段:
17.2.2.3 锁定子过程
你可以在一个子过程上加一把锁:

lock &func;

和数据锁不一样,数据锁只有劝告性锁,而子过程锁是强制性的。除了拥有锁的线程以外其它线程都不能进入子过程。

考虑一下下面的代码,它包含一个涉及 $done 变量的冲突条件。(yield 只是用于演示)。


use Thread qw/async yield/;
my $done = 0;
sub frob {
        my $arg = shift;
        my $tid = Thread->self->tid;
        print "thread $tid: frob $arg\n";
        yield;
        unless ($done) {
                yield;
                $done++;
                frob($arg + 10);
        }
}如果你这样运行:


my @t;
for my $i (1..3) {
        push @t, Thread->new(\&frob, $i);
}
for (@t) { $_->join}
print "done is $done\n";下面是输出(哦,有时候是这样的——输出是不可预料的):


thread 1: frob 1
thread 2: frob 2
thread 3: frob 3
thread 1: frob 11
thread 2: frob 12
thread 3: frob 13
done is 3
不过如果你这么运行:


for my $i (1..3) {
        push @t, async {
                lock &frob;
                frob($i);
        };
}
for (@t) { $_->join }
print "done is $done\n";输出是下面的东西:


thread 1: frob 1
thread 1: frob 11
thread 2: frob 2
thread 3: frob 3
done is 1


不太明白,请教一下:
1,use Thread qw/async yield/;是什么意思?
2,$done这个变量如何被改变?我觉得unless那段应该不会运行

谢谢
另外,谁有perl多线程的文章,发个链接?谢谢
my $thr = threads->create({'context' => 'list'}, \&foo);
这种写法中,{'context' => 'list'}是什么意思?谢谢大侠们!
顶下
1,use Thread qw/async yield/;是什么意思?  

Re: Programming Perl 11.2 Creating Modules.
use Bestiary qw(ram @llama);     # Import the ram function and @llama array

use Thread qw/async yield/; # qw/async yield/ is a list of variable(s), function(s), etc

2,$done这个变量如何被改变?我觉得unless那段应该不会运行
$done is a global variable here, if you want to modify a variable by different threads, you can study CPAN Thread::Shared

my $thr = threads->create({'context' => 'list'}, \&foo);

{'context' => 'list'}: a referent to anonymous hash.
Same thing like below:
my %hash = ('context'=>'list');
my $hashref = \%hash;
my $thr = threads->create($hashref, \&foo);
谢谢楼上的解答,很详细:)
第二个问题我还是不太明白:
$done = 0
在线程中,unless($done)以后应该都不会执行的,$done++也就无法执行,不知我这样理解是否有误?谢谢


QUOTE:
原帖由 lifeistrue 于 2008-8-27 10:18 发表
谢谢楼上的解答,很详细:)
第二个问题我还是不太明白:
$done = 0
在线程中,unless($done)以后应该都不会执行的,$done++也就无法执行,不知我这样理解是否有误?谢谢

我的理解是,不一定就不执行,因为你启动线程的这个时候$done还是0. 同时这也是为什么有不确定性。如果启动的3个线程到那个check的时候,done 还没变, 那么这个block就都能执行,里面有点race的意思。

结果可以是1,2, 3, 也有可能是2,3,1 。。。

如果你在for loop 里面加个sleep,我估计也就只能执行一次了。

用lock和没用的,打印结果比较一下,就是这个意思。加了lock之后,2 和 3 就去不了哪个block了。