微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

多线程 – 如何在Perl中控制多线程同步

我有[a-z,A-Z] ASCII数字的数组,如下所示:my @alphabet =(65..90,97..122);

所以主线程功能是从字母表中检查每个字符,如果条件为真则返回字符串.

简单的例子:

my @output = ();
    for my $ascii(@alphabet){
      thread->new(\sub{ return chr($ascii); });
    }

我想在每个ASCII号上运行线程,然后以正确的顺序将线程函数中的字母放入数组中.

所以在out case数组@output应该是动态的并且在所有线程完成它们的工作之后包含[a..z,A-Z].

如何检查,是否已完成所有线程并保持订单?

解决方法

你正在寻找$thread-> join,它等待一个线程完成.记录 here,this SO question也可能有所帮助.

因为在你的情况下,看起来在线程中完成的工作在成本上大致相等(没有线程比任何其他线程花费更长的时间),你可以按顺序加入每个线程,就像这样,等待他们都完成了:

# Store all the threads for each letter in an array.
my @threads = map { thread->new(\sub{ return chr($_); }) } @alphabet;
my @results = map { $_->join } @threads;

因为,当第一个线程从join返回时,其他线程可能已经完成并且只是等待“join”来获取它们的返回代码,或者即将完成,这会让你非常接近“尽可能快”的并行性,并且,由于线程是按顺序创建的,因此@results已经免费订购.

现在,如果您的线程可能需要不同的时间来完成,或者您需要在将“子线程”结果插入输出数据结构之前在“主”/生成线程中执行一些耗时的处理,那么按顺序连接它们可能不太好.在这种情况下,您需要以某种方式:a)检测线程“退出”事件,或者b)轮询以查看哪些线程已退出.

您可以使用从子线程发送到主/生成线程的信号/通知来检测线程“退出”事件.最简单/最常用的方法是使用threads::shared中的cond_wait和cond_signal函数.主线程将等待来自子线程的信号,处理它们的输出,并将其存储到结果数组中.如果你采用这种方法,你应该将结果数组预先分配到正确的大小,并为你的线程提供输出索引(例如,在创建线程时使用C风格的for循环并让它们返回($result,$index_to_store)或类似的)所以你可以将结果存储在正确的位置,即使它们没有故障.

您可以使用is_joinable线程实例方法轮询完成哪些线程,或者在循环中使用threads-> list(threads :: joinable)和threads-> list(threads :: running)方法(希望不是繁忙的)等待一个;添加一个睡眠呼叫 – 即使是从Time::HiRes开始的亚秒级呼叫 – 将在这种情况下节省大量性能/电池)以检测事情何时完成并获取结果.

重要提示:产生大量线程以并行执行大量工作,特别是如果工作量小/快速完成,可能会导致性能问题,并且使用较少数量的线程可能会更好而不是一件“工作”(例如,产生少量线程,并且每个线程使用线程::共享函数来锁定并弹出“工作要做”的共享数组中的第一个项目而不是映射以1:1的方式处理线程. 1:1映射会产生两个主要的性能问题:

>产生和加入每个线程的开销(内存和时间)远远高于你的想象(benchmark它在线程上没有做任何事情,只是返回,看看).如果您需要做的工作很快,那么大量线程的线程管理开销会比仅管理一些可重用的线程慢得多.
>如果最终得到的线程比逻辑cpu核心多得多,并且每个线程正在进行cpu密集型工作,或者每个线程正在访问相同的资源(例如,从相同的磁盘或数据库中的相同行读取),你很快就遇到了表演悬崖.将线程数量调整到下面的“资源”(无论是cpu还是硬盘驱动器或诸如此类)往往会产生比线程调度程序在更多线程之间切换而不是运行它们的可用资源更好的吞吐量.这个原因很慢的原因非常广泛:
>因为线程调度程序(操作系统的一部分,而不是语言)无法充分了解每个线程正在尝试做什么,所以preemptive scheduling无法针对某一点优化性能,因为知识有限.
>操作系统通常试图给大多数线程一个合理公平的镜头,所以它不能可靠地说“让一个运行完成然后运行下一个”,除非你明确地将其加入代码中(因为替代方案会无法预测地挨饿)某些线程有机会运行).基本上,在“在资源X上运行一个线程1”和“在资源X上运行一个线程2”之间进行切换,一旦有了比线程更多的线程,就不会得到任何东西,并且还会增加一些开销.

TL; DR线程不会在一定时间内提高性能,在此之后它们会使性能变差.如果可以,请重用与可用资源相对应的多个线程;不要创建/销毁与需要完成的任务相对应的单个线程.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐