Instructies voor: Gelijktijdige bewerkingen synchroniseren met een barrière
In het volgende voorbeeld ziet u hoe u gelijktijdige taken synchroniseert met een Barrier.
Voorbeeld
Het doel van het volgende programma is om te tellen hoeveel iteraties (of fasen) nodig zijn om ervoor te zorgen dat twee threads elk hun helft van de oplossing vinden in dezelfde fase, door gebruik te maken van een randomiserend algoritme om de woorden opnieuw te schikken. Nadat elke thread de woorden in willekeurige volgorde heeft geplaatst, vergelijkt de barrière-na-fase bewerking de twee resultaten om te zien of de volledige zin in de juiste woordvolgorde is weergegeven.
//#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 {barrier.CurrentPhaseNumber} attempts");
}
});
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
Een Barrier is een object dat voorkomt dat afzonderlijke taken in een parallelle bewerking worden voortgezet totdat alle taken de barrière bereiken. Het is handig wanneer een parallelle bewerking plaatsvindt in fasen en elke fase synchronisatie tussen taken vereist. In dit voorbeeld zijn er twee fasen voor de bewerking. In de eerste fase vult elke taak de sectie van de buffer met gegevens. Wanneer elke taak klaar is met het vullen van de sectie, geeft de taak de barrière aan dat deze klaar is om door te gaan en wacht vervolgens. Wanneer alle taken de barrière hebben gesignaleerd, worden ze gedeblokkeerd en wordt de tweede fase gestart. De barrière is nodig omdat de tweede fase vereist dat elke taak toegang heeft tot alle gegevens die tot dit punt zijn gegenereerd. Zonder de barrière kunnen de eerste taken die moeten worden voltooid, proberen te lezen uit buffers die nog niet zijn ingevuld door andere taken. U kunt op deze manier een willekeurig aantal fasen synchroniseren.