Så här synkroniserar du samtidiga åtgärder med en barriär
I följande exempel visas hur du synkroniserar samtidiga uppgifter med en Barrier.
Exempel
Syftet med följande program är att räkna hur många iterationer (eller faser) som krävs för att två trådar ska hitta hälften av lösningen i samma fas med hjälp av en randomiserande algoritm för att omskapa orden. När varje tråd har blandat sina ord jämför barriären efter fas de två resultaten för att se om den fullständiga meningen har renderats i rätt ordordning.
//#define TRACE
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace BarrierSimple
{
class Program
{
static string[] words1 = new string[] { "brown", "jumps", "the", "fox", "quick"};
static string[] words2 = new string[] { "dog", "lazy","the","over"};
static string solution = "the quick brown fox jumps over the lazy dog.";
static bool success = false;
static Barrier barrier = new Barrier(2, (b) =>
{
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);
if (String.CompareOrdinal(solution, sb.ToString()) == 0)
{
success = true;
Console.WriteLine("\r\nThe solution was found in {0} attempts", barrier.CurrentPhaseNumber);
}
});
static void Main(string[] args)
{
Thread t1 = new Thread(() => Solve(words1));
Thread t2 = new Thread(() => Solve(words2));
t1.Start();
t2.Start();
// Keep the console window open.
Console.ReadLine();
}
// Use Knuth-Fisher-Yates shuffle to randomly reorder each array.
// For simplicity, we require that both wordArrays be solved in the same phase.
// Success of right or left side only is not stored and does not count.
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;
}
// We need to stop here to examine results
// of all thread activity. This is done in the post-phase
// delegate that is defined in the Barrier constructor.
barrier.SignalAndWait();
}
}
}
}
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Threading
Imports System.Threading.Tasks
Class Program
Shared words1() = New String() {"brown", "jumps", "the", "fox", "quick"}
Shared words2() = New String() {"dog", "lazy", "the", "over"}
Shared solution = "the quick brown fox jumps over the lazy dog."
Shared success = False
Shared barrier = New Barrier(2, Sub(b)
Dim sb = New StringBuilder()
For i As Integer = 0 To words1.Length - 1
sb.Append(words1(i))
sb.Append(" ")
Next
For i As Integer = 0 To words2.Length - 1
sb.Append(words2(i))
If (i < words2.Length - 1) Then
sb.Append(" ")
End If
Next
sb.Append(".")
System.Diagnostics.Trace.WriteLine(sb.ToString())
Console.CursorLeft = 0
Console.Write("Current phase: {0}", barrier.CurrentPhaseNumber)
If (String.CompareOrdinal(solution, sb.ToString()) = 0) Then
success = True
Console.WriteLine()
Console.WriteLine("The solution was found in {0} attempts", barrier.CurrentPhaseNumber)
End If
End Sub)
Shared Sub Main()
Dim t1 = New Thread(Sub() Solve(words1))
Dim t2 = New Thread(Sub() Solve(words2))
t1.Start()
t2.Start()
' Keep the console window open.
Console.ReadLine()
End Sub
' Use Knuth-Fisher-Yates shuffle to randomly reorder each array.
' For simplicity, we require that both wordArrays be solved in the same phase.
' Success of right or left side only is not stored and does not count.
Shared Sub Solve(ByVal wordArray As String())
While success = False
Dim rand = New Random()
For i As Integer = 0 To wordArray.Length - 1
Dim swapIndex As Integer = rand.Next(i + 1)
Dim temp As String = wordArray(i)
wordArray(i) = wordArray(swapIndex)
wordArray(swapIndex) = temp
Next
' We need to stop here to examine results
' of all thread activity. This is done in the post-phase
' delegate that is defined in the Barrier constructor.
barrier.SignalAndWait()
End While
End Sub
End Class
A Barrier är ett objekt som förhindrar att enskilda uppgifter i en parallell åtgärd fortsätter tills alla aktiviteter når barriären. Det är användbart när en parallell åtgärd inträffar i faser och varje fas kräver synkronisering mellan aktiviteter. I det här exemplet finns det två faser i åtgärden. I den första fasen fyller varje aktivitet sin del av bufferten med data. När varje uppgift är klar med att fylla sitt avsnitt signalerar uppgiften barriären att den är redo att fortsätta och väntar sedan. När alla uppgifter har signalerat barriären avblockeras de och den andra fasen startar. Barriären är nödvändig eftersom den andra fasen kräver att varje uppgift har åtkomst till alla data som har genererats till den här punkten. Utan barriären kan de första uppgifterna som ska slutföras försöka läsa från buffertar som ännu inte har fyllts i av andra uppgifter. Du kan synkronisera valfritt antal faser på det här sättet.