• .NET同步Barrier(阶段)【项目中不同阶段、碰头会】


    Barrier(屏障)是一种自定义的同步原语(synchronization primitive),它解决了多个线程(参与者)在多个阶段之间的并发和协调问题。

    1)多个参与者执行相同的几个阶段的操作

    2)在每一个阶段内,多个参与者并发执行

    3)一个屏障点代表一个阶段的结束

    4)一个参与者运行至屏障点时被阻塞,需要等待其他参与者都到达屏障点

    5)所有参与者都到达了屏障点,才可以进入下一个阶段

    创建Barrier时,需要指定参与者数量。它允许动态的添加或者删除参与者。

    Barrier适合多个线程执行多个阶段的操作。如果只有一个或两个阶段,可以考虑ContinueWhenAll。

    下面是一个简单的例子。4个线程执行执行4个阶段。

    四个阶段的代码。(每个阶段只是输出文本,表示某个阶段的某个任务结束)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    private static void RunPhase1(int taskId)
    {
        Console.WriteLine("phase 1, task {0} completed", taskId);
    }
    private static void RunPhase2(int taskId)
    {
        Console.WriteLine("phase 2, task {0} completed", taskId);
    }
    private static void RunPhase3(int taskId)
    {
        Console.WriteLine("phase 3, task {0} completed", taskId);
    }
    private static void RunPhase4(int taskId)
    {
        Console.WriteLine("phase 4, task {0} completed", taskId);
    }

    Barrier代码。(定义参与者数量,以及到达屏障点所做的事情,即输出文本宝石当前阶段结束) 

    1
    2
    3
    4
    5
    private static Barrier barrier = new Barrier(4, (b) =>
    {
        Console.WriteLine("phase {0} completed", b.CurrentPhaseNumber);
        Console.WriteLine();
    });

    Main方法代码。(创建4个任务,执行四个阶段,每个阶段结束时调用SignalAndWait方法设立屏障点)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    static void Main(string[] args)
    {
        var tasks = new List<Task>();
        for (var i = 0; i < 4; i++)
        {
            tasks.Add(Task.Factory.StartNew((index) =>
            {
                var taskId = (int)index;
     
                RunPhase1(taskId);
                barrier.SignalAndWait();
     
                RunPhase2(taskId);
                barrier.SignalAndWait();
     
                RunPhase3(taskId);
                barrier.SignalAndWait();
     
                RunPhase4(taskId);
                barrier.SignalAndWait();
     
            }, i));
        }
     
        var finalTask = Task.Factory.ContinueWhenAll(tasks.ToArray(), (taskList) =>
        {
            Task.WaitAll(taskList);
            Console.WriteLine("all phases completed");
            barrier.Dispose();
        });
        finalTask.Wait();
     
        Console.ReadLine();
    }

    运行代码,查看结果。您会发现4个任务在每个阶段的完成顺序不太一样,所有任务完成后才进入下一个阶段。

    再来看一个示例:

          static void Main(string[] args)
            {
                var t1 = new Thread(() => PlayMusic("the 吉他手", "演奏一首精彩的独奏曲", 5));
                var t2 = new Thread(() => PlayMusic("the 歌手", "唱他的歌", 2));
    
                t1.Start();
                t2.Start();
                Console.Read();
            }
    
            static Barrier _barrier = new Barrier(2,
        b => Console.WriteLine("完成阶段 {0}", b.CurrentPhaseNumber + 1));
    
            static void PlayMusic(string name, string message, int seconds)
            {
                for (int i = 1; i < 3; i++)
                {
                    //每个线程,先完成一些任务
                    Console.WriteLine("----------------------------------------------");
                    Thread.Sleep(TimeSpan.FromSeconds(seconds));
                    Console.WriteLine("{0} 开始 {1}", name, message);
                    Thread.Sleep(TimeSpan.FromSeconds(seconds));
                    Console.WriteLine("{0} 完成 {1}", name, message);
    
                    //完成了一个阶段任务,每个线程到这里都会执行一个回调函数,打印出阶段内容(_barrier对象中的匿名函数)
                    _barrier.SignalAndWait();
                }
            }

  • 相关阅读:
    webuploader 上传文件参数设置
    数据库报插入异常
    System.Threading.Timer 定时器的用法
    JSON 获取属性值的方法
    JAVA Socket 编程学习笔记(二)
    JAVA Socket 编程学习笔记(一)
    JAVA 判断Socket 远程端是否断开连接
    JAVA 多线程和并发学习笔记(四)
    JAVA 多线程和并发学习笔记(三)
    巧用transform实现HTML5 video标签视频比例拉伸
  • 原文地址:https://www.cnblogs.com/gougou1981/p/12365407.html
Copyright © 2020-2023  润新知