首页 > 作文

C#多线程系列之多阶段并行线程

更新时间:2023-04-05 00:16:48 阅读: 评论:0

前言

这一篇,我们将学习用于实现并行任务、使得多个线程有序同步完成多个阶段的任务。

应用场景主要是控制 n 个线程(可随时增加或减少执行的线程),使得多线程在能够在 m 个阶段中保持同步。

线程工作情况如下:

我们接下来 将学习c# 中的 barrier ,用于实现并行协同工作。

barrier 类

使多个任务能够采用并行方式依据某种算法在多个阶段中协同工作,使多个线程(称为“参与者” )分阶段同时处理算法。

可以使多个线程(称为“参与者” )分阶段同时处理算法。(注意算法这个词)

每个参与者完成阶段任务后后将被阻止继续执行,直至所有参与者都已达到同一阶段。

barrier 的构造函数如下:

构造函数说明barrier(int32)初始化 barrier 类的新实例。barrier(int32, action)初始化 barrier 类的新实例。

其中一个构造函数定义如下:

public barrier (int participantcount, action<barrier> postphaaction);

participantcount :处于的线程数量,大于0并且小于32767。

postphaaction :在每个阶段后执行 action(委托)。

属性和方法

在还没有清楚这个类有什么作用前,我们来看一下这个类的常用属性和方法。

大概了解 barrier 有哪些常用属性和方法后,我们开始编写示例代码。

属性:

属性说明currentphanumber获取屏障的当前阶段的编号。participantcount获取屏障中参与者的总数。participantsremaining获取屏障中尚未在当前阶段发出信号的参与者的数量。

方法:

方法说明addparticipant()通知 barrier,告知其将会有另一个参与者。addparticipants(int32)通知 barrier,告知其将会有多个其他参与者。removeparticipant()通知 barrier,告知其将会减少一个参与者。removeparticipants(int32)通知 barrier,告知其将会减少一些参与者。signalandwait()发出参与者已达到屏障并等待所有其他参与者也达到屏障。signalandwait(cancellationtoken)发出参与者已达到屏障的信号,并等待所有其他参与者达到屏障,同时观察取消标记。signalandwait(int我爱你怎么说32)发出参与者已达到屏障的信号,并等待所有其他参与者也达到屏障,同时使用 32 位带符号整数测量超时。signalandwait(int32, cancellationtoken)发出参与者已达到屏障的信号,并等待所有其他参与者也达到屏障,使用 32 位带符号整数测量超时,同时观察取消标记。signalandwait(timespan)发出参与者已达到屏障的信号,并等迪拜人工岛待所有其他参与者也达到屏障,同时使用 timespan 对象测量时间间隔。signalandwait(timespan, cancellationtoken)发出参与者已达到屏障的信号,并等待所有其他参与者也达到屏障,使用 timespan 对象测量时间间隔,同时观察取消标记。

barrier 翻译屏障,前面所说的 “阶段”,在文档中称为屏障,官方有一些例子和实践场景:

https://docs.microsoft.com/zh-cn/dotnet/standard/threading/barrier?view=netcore-3.1

https://docs.microsoft.com/zh-cn/dotnet/standard/threading/how-to-synchronize-concurrent-operations-with-a-barrier?view=netcore-3.1

本文的教程比较简单,你可以先看本教程,再去看看官方示例。

示例

假设有个比赛,一个有三个环节,有三个小组参加比赛。

比赛有三个环节,小组完成一个环节后,可以去等待区休息,等待其他小组也完成比赛后,开始进行下一个环节的比赛。

示例如下:

new barrier(int,action)设置有多少线程参与,acti入党过程on 委托设置每个阶段完成后执行哪些动作。

.signalandwait()阻止当前线程继续往下执行;直到其他完成也执行到此为止。

    class program    {        // barrier(int32, action)        private static barrier barrier = new barrier(3, b =>                            console.writeline($"\n第 {b.currentphanumber + 1} 环节的比赛结束,请评分!"));        static void main(string[] args)        {            // random 模拟每个小组完成一个环节比赛需要的时间            thread thread1 = new thread(() => dowork("第一小组", new random().next(2, 10)));            thread t通知书怎么写hread2 = new thread(() => dowork("第二小组", new random().next(2, 10)));            thread thread3 = new thread(() => dowork("第三小组", new random().next(2, 10)));            // 三个小组开始比赛            thread1.start();            thread2.start();            thread3.start();            console.readkey();        }        static void dowork(string name, int conds)        {            // 第一环节            console.writeline($"\n{name}:开始进入第一环节比赛");            thread.sleep(timespan.fromconds(conds));    // 模拟小组完成环节比赛需要的时间            console.writeline($"\n    {name}:完成第一环节比赛,等待其它小组");            // 小组完成阶段任务,去休息等待其它小组也完成比赛            barrier.signalandwait();            // 第二环节            console.writeline($"\n        {name}:开始进入第二环节比赛");            thread.sleep(timespan.fromconds(conds));            console.writeline($"\n        {name}:完成第二环节比赛,等待其它小组\n");            barrier.signalandwait();            // 第三环节            console.writeline($"\n        {name}:开始进入第三环节比赛");            thread.sleep(timespan.fromconds(conds));            console.writeline($"\n        {name}:完成第三环节比赛,等待其它小组\n");            barrier.signalandwait();        }    }

上面的示例中,每个线程都使用了dowork()这个方法去中相同的事情,当然也可以设置多个线程执行不同的任务,但是必须保证每个线程都具有相同数量的.signalandwait();方法。

当然signalandwait()可以设置等待时间,如果其他线程迟迟没有到这一步,那就继续运行。可以避免死锁等问题。

到目前,只使用了signalandwait(),我们继续学习一下 barrier 类的其他方法。

零花钱调查报告新的示例

barrier.addparticipant():添加参与者;

barrier.removeparticipant():移除参与者;

这里继续使用第二节的示例。

因为这是比赛,老是等待其他小组,会使得比赛进行比较慢。

新的规则:不必等待最后一名,当环节只剩下最后一名时为完成时,其它小组可以立即进行下一个环节的比赛。

​ 当然,最后一名小组,有权利继续完成比赛。

修改第二小节的代码,在 main 内第一行加上barrier.removeparticipant();

        static void main(string[] args)        {            barrier.removeparticipant();            ... ...

试着再运行一下。

说明

signalandwait()的 重载比较多,例如signalandwait(cancellationtoken),这里笔者先不讲解此方法如何使用。等到写到后面的异步(task),读者学到相关的知识点,我们再过一次复习,这样由易到难,自然水到渠成。

barrier 适合用于同时执行相同流程的工作,因为工作内容是相同的,便于协同。工作流有可能用得上吧。

但是 barrier 更加适合用于算法领域,可以参考:https://devblogs.microsoft.com/pfxteam/parallel-merge-sort-using-barrier/

到此这篇关于c#多线程系列之多阶段并行线程的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持www.887551.com。

本文发布于:2023-04-05 00:16:44,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/a2657026e79e5aa0e38a3261bcfeb12d.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:C#多线程系列之多阶段并行线程.doc

本文 PDF 下载地址:C#多线程系列之多阶段并行线程.pdf

标签:参与者   屏障   线程   环节
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图