zoukankan      html  css  js  c++  java
  • 屏障

    屏障

    关卡是一个用户定义的同步基元,它使多个线程(称为“参与者”)可以分阶段同时参与执行一个算法。 每个参与者将执行到代码中的关卡点为止。 关卡表示一个阶段的工作结束。 当某个参与者到达关卡时,它将阻塞,直至所有参与者都已到达同一关卡为止。 在所有参与者都已到达关卡之后,您可以选择调用后期阶段操作。 在所有其他线程仍被阻塞时,单个线程可以使用此后期阶段操作来执行操作。 在执行该操作之后,所有参与者都将被取消阻塞。

    添加和删除参与者

    创建 Barrier 时,指定参与者的数量。 也可在任何时间动态地添加或移除参与者

    出现故障的关卡

    如果一个参与者未能到达关卡,则会发生死锁。 若要避免这些死锁,请使用 SignalAndWait 方法的重载来指定超时期限和取消标记。 这些重载将返回一个布尔值,每个参与者都会在它继续下一阶段之前检查该值。

    后期阶段异常

    如果后期阶段委托引发异常,则在 BarrierPostPhaseException 对象中包装它,然后将其传播到所有参与者。

    关卡与ContinueWhenAll

    当线程循环执行多个阶段时,关卡尤其有用。 如果您的代码只需要一个或两个阶段的工作,请考虑是否使用带有各种隐式联接的 System.Threading.Tasks.Task 对象

    一个Demo:

    using System;
    using System.Text;
    using System.Threading;
    
    namespace MyConsole2
    {
        class Program
        {
    
            static string[] words1 = new string[] { "brown", "jumped", "the", "fox", "quick" };
            static string[] words2 = new string[] { "dog", "lazy", "the", "over" };
            static string solution = "the quick brown fox jumped over the lazy dog.";
    
            static bool success = false;
    
            static Barrier barrier = new Barrier(1, //参与线程的数量
                b =>  // 要在每个阶段后执行的操作。 可以传递 null
                {
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < words1.Length; i++)
                {
                    sb.Append(words1[i]);
                    sb.Append(" ");
                }
                for (int i = 0; i < words2.Length; i++)
                {
                    sb.Append(words2[i]);
                    if (i < words2.Length - 1)
                        sb.Append(" ");
                }
                sb.Append(".");
    #if TRACE
                System.Diagnostics.Trace.WriteLine(sb.ToString());
    #endif
                Console.CursorLeft = 0;
                Console.Write("Current phase: {0}", barrier.CurrentPhaseNumber);
                Console.WriteLine("thread ID:"+Thread.CurrentThread.ManagedThreadId);
                if (String.CompareOrdinal(solution, sb.ToString()) == 0)
                {
                    success = true;
                    Console.WriteLine("
    The solution was found in {0} attempts", barrier.CurrentPhaseNumber); Console.WriteLine();
                }
            });
    
            static void Solve(string[] wordArray)
            {
                while (success==false)
                {
                    Random random = new Random();
                    for (int i = wordArray.Length - 1; i > 0; i--)
                    {
                        int swapIndex = random.Next(i+1);
                        string temp = wordArray[i];
                        wordArray[i] = wordArray[swapIndex];
                        wordArray[swapIndex] = temp;
                    }
                    //等待其它参与者到达
                    barrier.SignalAndWait();
                }
            }
            static void Main(string[] args)
            {
                Thread t1 = new Thread(() => Solve(words1));
                Thread t2 = new Thread(() => Solve(words2));
                barrier.AddParticipant();//添加一个参与者
                t1.Start();
                t2.Start();
    
                Console.ReadLine();
            }
    
             
    
        }
    

    }

  • 相关阅读:
    Should I expose synchronous wrappers for asynchronous methods?
    .NET Memory Allocation Profiling with Visual Studio 2012
    Should I expose asynchronous wrappers for synchronous methods?
    Patterns for Asynchronous MVVM Applications: Commands
    WPF/SL: lazy loading TreeView
    Reusable async validation for WPF with Prism 5
    Entity Framework Code First
    ConsoleHelper 类
    [Forward]Sweeping the IDisposable minefield
    Enums and Lookup Tables with EF Code First
  • 原文地址:https://www.cnblogs.com/goodlucklzq/p/4487943.html
Copyright © 2011-2022 走看看