我有一个 perl 对象,其中有一些函数。每个函数从主程序中调用一次。我想并行运行一些函数以节省时间。我无法同时运行所有函数,因为某些函数依赖于先前函数的结果。
我想到了这样的事情:
- 对于每个函数,保留一个初始化为 false 的标志,并在函数结束时将其设置为 true(例如
func1
中的最后一行将是$is_func1_done = 1
)。 用一个循环启动每个函数,该循环等待直到它所依赖的函数的所有标志都为 true。例如:如果
func1
取决于func2
和func3
那么:sub func1 { while (!($is_func2_done && $is_func3_done)) { # do nothing } # do work }
然后我可以立即为每个函数启动一个线程,但每个函数的实际工作只有在准备就绪时才会开始。这有道理吗?我需要在旗帜上加锁吗?正在使用这样的while
循环常见吗? -- 脑海中浮现“忙等待”这个词...也许我的大部分CPU时间都会花在这些while
上是?有没有更标准的解决方案?
最佳答案
Does this make sense?
是的 - 每个任务都知道其先决条件,并在执行之前等待它们满足。它是众多有效设计之一,尽管您可能会发现随着任务数量的增加以及它们的相互依赖性变得更加复杂而难以扩展。
Do I need any locks here on the flags?
是的。标志需要是 shared ,以便一个线程可以操作它们,而另一个线程可以看到它,并且共享变量需要 lock()
才能安全使用。
Is using such while loops common? -- the term busy waiting comes to mind
遗憾的是,是的,但是请不要这样做。perl 中的共享变量可以用作条件变量,线程可以通过它向彼此发送通知: p>
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
时,共享变量将被解锁并且您的线程将进入休眠状态。无需繁忙循环。
Is there a more standard solution to this?
$thr->join
,如 Sinan suggests ,是等待特定线程完成运行的一种简单而自然的方法。 Thread::Semaphore可以提供类似但更复杂的功能(并且可以将其初始化为小于零的值)。 “等待这 5 个线程完成某件事”的常见需求可以通过 Thread::Barrier 来实现。 。 TMTOWTDI。
关于multithreading - Perl 中的线程同步/调度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3470184/