System.Threading.Barrier多线程屏障类,分界线

83 篇文章 3 订阅

Barrier:屏障,障碍,分界线
使多个任务能够采用并行方式依据某种算法在多个阶段中协同工作。

多个线程各自执行完毕,合并一起后再往下执行其他事件

在Barrier之前,若干个thread各自执行,然后到了Barrier的时候停下,等待规定数目的所有的其他线程到达这个Barrier,之后再一起通过这个Barrier各自干自己的事情。

比如:大家从各自的工位到会议室集合,待人数都到齐(Barrier)之后,开始会议并讨论问题。

Task.WaitAll(Task1,Task2,Task3,....);

DoSomething();

注解

通过一系列阶段共同合作的一组任务,其中每个阶段都在每个阶段到达, Barrier 并隐式等待所有其他阶段到达。 相同的 Barrier 可用于多个阶段。

属性

属性
CurrentPhaseNumber

获取屏障的当前阶段的编号。

ParticipantCount

获取屏障中参与者的总数。

ParticipantsRemaining

获取屏障中尚未在当前阶段发出信号的参与者的数量。

方法

方法
AddParticipant()

通知 Barrier,告知其将会有另一个参与者。

AddParticipants(Int32)

通知 Barrier,告知其将会有多个其他参与者。

Dispose()

释放 Barrier 类的当前实例所使用的所有资源。

RemoveParticipant()

通知 Barrier,告知其将会减少一个参与者。

RemoveParticipants(Int32)

通知 Barrier,告知其将会减少一些参与者。

SignalAndWait()

发出参与者已达到屏障并等待所有其他参与者也达到屏障。

SignalAndWait(CancellationToken)

发出参与者已达到屏障的信号,并等待所有其他参与者达到屏障,同时观察取消标记。

SignalAndWait(Int32)

发出参与者已达到屏障的信号,并等待所有其他参与者也达到屏障,同时使用 32 位带符号整数测量超时。

SignalAndWait(Int32, CancellationToken)

发出参与者已达到屏障的信号,并等待所有其他参与者也达到屏障,使用 32 位带符号整数测量超时,同时观察取消标记。

SignalAndWait(TimeSpan)

发出参与者已达到屏障的信号,并等待所有其他参与者也达到屏障,同时使用 TimeSpan 对象测量时间间隔。

SignalAndWait(TimeSpan, CancellationToken)

发出参与者已达到屏障的信号,并等待所有其他参与者也达到屏障,使用 TimeSpan 对象测量时间间隔,同时观察取消标记。

//参考文档
https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.barrier?view=netcore-3.1
            //源代码:
            //https://referencesource.microsoft.com/#System/sys/system/threading/Barrier.cs,6ff43d8403f8e835

            //Barrier:屏障,障碍,分界线
            //使多个任务能够采用并行方式依据某种算法在多个阶段中协同工作。
            /*
             * 主要是用作集合线程,然后再一起往下执行。
             * 再具体一点,在Barrier之前,若干个thread各自执行,然后到了Barrier的时候停下,等待规定数目的所有的其他线程到达这个Barrier,之后再一起通过这个Barrier各自干自己的事情。
             * 集体活动的过程,大家从各自的家里到学校集合,待人数都到齐(Barrier)之后,之后再一起坐车出去,到达指定地点后一起行动或者各自行动。
            */

新建控制台应用程序BarrierDemo:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace BarrierDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.SetWindowSize(100, 30);
            Barrier barrier = new Barrier(4, b =>
            {
                Console.WriteLine($"每个阶段完成【所有参与者都达到屏障,SignalAndWait()之后】之后执行。参与者总数:{b.ParticipantCount},当前阶段:{b.CurrentPhaseNumber}");
            });
            Console.WriteLine($"初始参与者个数:【{barrier.ParticipantCount}】");
            barrier.AddParticipants(2);
            Console.WriteLine($"增加2个参与者,当前参与者个数:【{barrier.ParticipantCount}】");
            barrier.RemoveParticipant();
            Console.WriteLine($"减少1个参与者,当前参与者个数:【{barrier.ParticipantCount}】");

            int count = 0;
            Action action = new Action(() => 
            {
                Interlocked.Increment(ref count);
                //用信号通知参与者已达到屏障,并等待所有其他参与者到达屏障。所有人每到达一次屏障,则当前阶段就加一
                barrier.SignalAndWait(); 
                Console.WriteLine($"当前线程编号:【{Thread.CurrentThread.ManagedThreadId}】计数器:【{count}】参与者总数:{barrier.ParticipantCount},当前阶段:{barrier.CurrentPhaseNumber}");
                Interlocked.Increment(ref count);
                barrier.SignalAndWait(); 
                Console.WriteLine($"当前线程编号:【{Thread.CurrentThread.ManagedThreadId}】计数器:【{count}】参与者总数:{barrier.ParticipantCount},当前阶段:{barrier.CurrentPhaseNumber}");
                
                Interlocked.Increment(ref count);
                try
                {
                    barrier.SignalAndWait();
                    Console.WriteLine($"当前线程编号:【{Thread.CurrentThread.ManagedThreadId}】计数器:【{count}】参与者总数:{barrier.ParticipantCount},当前阶段:{barrier.CurrentPhaseNumber}");
                }
                catch (BarrierPostPhaseException bppe)
                {
                    Console.WriteLine("Caught BarrierPostPhaseException: {0}", bppe.Message);
                }

                Interlocked.Increment(ref count);
                barrier.SignalAndWait(); 
                Console.WriteLine($"当前线程编号:【{Thread.CurrentThread.ManagedThreadId}】计数器:【{count}】参与者总数:{barrier.ParticipantCount},当前阶段:{barrier.CurrentPhaseNumber}");
            });

            //注意:为了确保所有的参与者都已执行,因此:并行的委托个数 一定是参与者总数【barrier.ParticipantCount】
            Action[] actionCollection = new Action[barrier.ParticipantCount];
            for (int i = 0; i < actionCollection.Length; i++)
            {
                actionCollection[i] = action;
            }
            Parallel.Invoke(actionCollection);          
            
            barrier.Dispose();
            Console.ReadLine();
        }
    }
}
 

运行效果如图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

斯内科

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值