我有一个带有一些函数的perl对象。每个函数都从主程序调用一次。我想并行运行一些函数以节省时间。我无法将所有这些功能一起运行,因为某些功能取决于先前功能的结果。
我想到了这样的事情:
func1
中的最后一行将为$is_func1_done = 1
)。使用循环启动每个函数,该循环等待它所依赖的函数的所有标志都为真。例如:如果func1
取决于func2
和func3
,那么:
sub func1 {
while (!($is_func2_done && $is_func3_done)) {
# do nothing
}
# do work
}
然后我可以立即为每个函数启动一个线程,但每个函数的实际工作只有在它准备就绪时才会启动。这有意义吗?旗帜上是否需要锁定?使用这种while
循环常见吗? - 想到忙碌的等待一词......也许我的大部分CPU时间将花在这些while
上?对此有更标准的解决方案吗?
答案 0 :(得分:2)
您应该使用$thr->join
等待线程完成。
例如:
#!/usr/bin/perl
use strict; use warnings;
use threads;
my @threads = map threads->create($_), qw( func1 func2 );
$_->join for @threads;
my $thr3 = threads->create('func3');
$thr3->join;
sub func1 {
for (1 .. 5) {
print "func1\n";
sleep 1 + rand 3;
}
return;
}
sub func2 {
for (1 .. 5) {
print "func2\n";
sleep 1 + rand 2;
}
return;
}
sub func3 {
print "Time to do some work\n";
}
我不知道使用这样的while
循环是否常见:我不会。
答案 1 :(得分:2)
这有意义吗?
是 - 每个任务都知道它的前提条件,并等待它们在执行前得到满足。它是众多有效设计中的一种,但随着任务数量的增加和相互依赖性变得更加复杂,您可能会发现难以扩展。
旗帜上是否需要锁定?
是。标志需要为shared,以便一个线程可以操作它们而另一个线程可以看到它,共享变量需要lock()
才能安全使用。
使用这种while循环常见吗? - 想到忙碌的等待一词
可悲的是,但不要这样做,请。 perl中的共享变量可以作为条件变量,线程可以通过它们发送通知:
sub func1 {
{
lock(%shared_state);
until ($shared_state{ "func2 done" } and $shared_state{ "func3 done" }) {
cond_wait(%shared_state);
}
}
# do work -- note that %shared_state is unlocked
# now tell others that we're done
lock(%shared_state);
$shared_state{ "func1 done" } = 1;
cond_broadcast(%shared_state);
# %shared_state will be unlocked, and broadcast delivered when we leave this scope
}
当你cond_wait
时,共享变量被解锁并且你的线程进入休眠状态。无需忙碌循环。
对此有更标准的解决方案吗?
$thr->join
,Sinan suggests,是等待特定线程完成运行的简单而自然的方法。 Thread::Semaphore可以提供类似但更复杂的功能(并且有用的是,可以初始化为小于零的值)。使用Thread::Barrier可以实现“等待这5个线程完成某些事情”的常见需求。 TMTOWTDI。