Skip to content

Instantly share code, notes, and snippets.

@ryunp
Last active October 25, 2022 00:30
Show Gist options
  • Save ryunp/07e79d922306ba229b285d9c1914756f to your computer and use it in GitHub Desktop.
Save ryunp/07e79d922306ba229b285d9c1914756f to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace ConcurrencyTest
{
class Program
{
static void Main(string[] args) => TestParallel();
// App settings
static readonly int MAX_ITERATIONS = 1000;
static readonly int MAX_THREADS = 3;
static readonly bool DISPLAY_INLINE = true;
static ConcurrentQueue<int> ConcurrentQ = new ConcurrentQueue<int>();
// Basic arithmetic functions
static int SumValuesFunc(int a, int b) => a + b;
static int SumValuesPlusSomeFunc(int a, int b) => SumValuesFunc(a, b) + 10;
static int SumValuesMinusSomeFunc(int a, int b) => SumValuesFunc(a, b) - MAX_ITERATIONS / 3;
// Value calculation interface
delegate int ValueCalcDelegate(int a, int b, string msg);
// Value calculation implementation
static int ValueCalcFunc(int a, int b, string msg)
{
if (!DISPLAY_INLINE) Console.WriteLine($"[{msg}] {a} {b}");
// (Change arithmetic function here)
return SumValuesFunc(a, b);
}
static void FillQueue()
{
for (int i = 0; i < MAX_ITERATIONS; i++)
ConcurrentQ.Enqueue(i);
}
// Test logic
static void TestParallel()
{
int serialSum = 0;
int parallelSum = 0;
int threadId = Thread.CurrentThread.ManagedThreadId;
List<Action> Actions = new List<Action>();
// Info header
Console.WriteLine($"Iterations: {MAX_ITERATIONS}, Threads: {MAX_THREADS}\n");
/*
* Serial summation
*/
Console.WriteLine("for (;;) {}");
for (int i = 0; i < MAX_ITERATIONS; i++)
serialSum = ValueCalcFunc(serialSum, i, $"Thread#{threadId}");
Console.WriteLine("\nResult: {0}, Expected: {1}\n\n", serialSum, serialSum);
/*
* Parallel summations
*/
// Create summation threads
for (int i = 0; i < MAX_THREADS; i++)
Actions.Add(() => PullFromCQAndAddToGlobalSum(ref ConcurrentQ, ref parallelSum, ValueCalcFunc));
// Using Task API
Console.WriteLine("Task.WaitAll()");
FillQueue();
Task.WaitAll(Actions.Select(a => Task.Run(a)).ToArray());
Console.WriteLine("\nResult: {0}, Expected: {1}\n\n", parallelSum, serialSum);
// Using Parallel API
Console.WriteLine("Parallel.Invoke()");
parallelSum = 0;
FillQueue();
Parallel.Invoke(Actions.ToArray());
Console.WriteLine("\nResult: {0}, Expected: {1}\n", parallelSum, serialSum);
}
// Thread safe Queue access logic
static void PullFromCQAndAddToGlobalSum(ref ConcurrentQueue<int> queue, ref int globalResult, ValueCalcDelegate calcValue)
{
var threadID = Thread.CurrentThread.ManagedThreadId.ToString();
var messages = new List<string>();
int localResult = 0;
string text;
text = $"Starting Thread #{threadID}";
if (DISPLAY_INLINE) Console.Write($" <{text}> "); else messages.Add($"{text}: ");
while (queue.TryDequeue(out int queueValue))
{
localResult = calcValue(localResult, queueValue, $"Thread#{threadID} ({queueValue})");
text = threadID;
if (DISPLAY_INLINE) Console.Write(text); else messages.Add(text);
}
text = string.Join("", messages).Trim();
if (DISPLAY_INLINE) Console.Write(text);
Interlocked.Add(ref globalResult, localResult);
}
}
}
Iterations: 1000, Threads: 3
for (;;) {}
Result: 499500, Expected: 499500
Task.WaitAll()
<Starting Thread #4> <Starting Thread #5> <Starting Thread #6> 4444444444444444444444444444445644444444444444444466666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666555555555555555555555555555555555555555555555555555555555555555555555555555555555555555566666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666644444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444466666666666666666666666666666666666666666666666666666666666666666666666666444444444444444444444444444444444444444444444444444444446666666666666666666666666666444444444444444444444444444444444444444444444466666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666644444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444465555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555556666666666666666666666666666666666666666666666666654
Result: 499500, Expected: 499500
Parallel.Invoke()
<Starting Thread #1> 1111111111111111 <Starting Thread #4> 444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444 <Starting Thread #8> 888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888844444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444488888888888888888888888888888888888881111111111111111111111144444444444444444444444444444444444444444444444444444444444444444444444444444444441111111111111111111111111111114444444444444448888888888888888888888888888888888888888888888888888888888888888811111111111111111444448888888888888888888888888888888888888888888888888888888888888888888888811111111111111111111111118888888888888888888888888888888444444444444444444444444444444444444444444444444444444444444444444444444444444448881444444444444444444444411111114444444444444444444444444444444444444444444444444444444444444444444444444444441118888881111111111111111111111111111111111111111111111111111111111111111114444444444444444481
Result: 499500, Expected: 499500
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment