屏障
屏障
关卡是一个用户定义的同步基元,它使多个线程(称为“参与者”)可以分阶段同时参与执行一个算法。 每个参与者将执行到代码中的关卡点为止。 关卡表示一个阶段的工作结束。 当某个参与者到达关卡时,它将阻塞,直至所有参与者都已到达同一关卡为止。 在所有参与者都已到达关卡之后,您可以选择调用后期阶段操作。 在所有其他线程仍被阻塞时,单个线程可以使用此后期阶段操作来执行操作。 在执行该操作之后,所有参与者都将被取消阻塞。
添加和删除参与者
创建 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("\r\nThe 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();
}
}
}