Files
gpd-925-en/Multithreading/RaceConditions.cs
T

110 lines
5.0 KiB
C#

using System;
using System.Text;
using System.Threading.Tasks;
namespace Multithreading
{
internal static class Program
{
private static readonly object _fileLock = new object();
public static void Main(string[] args)
{
Console.WriteLine("Program started");
// int[] numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// Task[] tasks = new Task[100];
// Random random = new Random();
// for (int i = 0; i < tasks.Length; i++)
// {
// tasks[i] = Task.Run(() =>
// {
// for (int j = 0; j < numbers.Length; j++)
// {
// Console.WriteLine($"Before Thread Id: {Thread.CurrentThread.ManagedThreadId}, number({j}): {numbers[j]}");
//
// Thread.Sleep(random.Next(0, 1000));
//
// // not thread-safe
// // int oldValue = numbers[j];
// // int newValue = oldValue * random.Next(10);
// // numbers[j] = newValue;
// // Thread.Sleep(random.Next(0, 1000));
// // Console.WriteLine($"After Thread Id: {Thread.CurrentThread.ManagedThreadId}, number({j}): {numbers[j]} / oldValue: {oldValue} / newValue: {newValue}");
//
// // making this thread-safe
// // option 1: lock
// lock (numbers)
// {
// int oldValue = numbers[j];
// int newValue = oldValue * random.Next(10);
// numbers[j] = newValue;
// Thread.Sleep(random.Next(0, 1000));
// Console.WriteLine($"After Thread Id: {Thread.CurrentThread.ManagedThreadId}, number({j}): {numbers[j]} / oldValue: {oldValue} / newValue: {newValue}");
// }
//
// // option 2: use concurrent collections
// // https://learn.microsoft.com/en-us/dotnet/standard/collections/thread-safe/
//
// // option 3: use chunks to have no overlapping
//
// }
// });
// }
// Dictionary<int, string> dictionary = new Dictionary<int, string>();
// Task[] tasks = new Task[1000];
// Random random = new Random();
// for (int i = 0; i < tasks.Length; i++)
// {
// tasks[i] = Task.Run(() =>
// {
// lock (dictionary) // one option, another option is to use ConcurrentDictionary
// {
// int key = random.Next();
// if (!dictionary.ContainsKey(key))
// {
// // dictionary[key] = $"Thread Id: {Thread.CurrentThread.ManagedThreadId}, number({key}): {random.Next(10)}";
// dictionary.TryAdd(key, $"Thread Id: {Thread.CurrentThread.ManagedThreadId}, number({key}): {random.Next(10)}");
// }
// }
// });
// }
Task[] tasks = new Task[100];
Random random = new Random();
File.Delete("output.txt");
for (int i = 0; i < tasks.Length; i++)
{
tasks[i] = Task.Run(() =>
{
// not thread-safe
// File.AppendAllText("output.txt", $"Thread Id: {Thread.CurrentThread.ManagedThreadId}, number: {random.Next(10)}\n");
// FileStream fs = File.OpenWrite("output.txt");
// FileStream fs = File.Open("output.txt", FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
// string s = $"{Thread.CurrentThread.ManagedThreadId}, number: {random.Next(10)}\n";
// byte[] bytes = Encoding.UTF8.GetBytes(s);
// fs.Write(bytes, 0, bytes.Length);
// fs.Close();
// fs.Dispose();
// thread-safe
lock (_fileLock)
{
FileStream fs = File.Open("output.txt", FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
string s = $"{Thread.CurrentThread.ManagedThreadId}, number: {random.Next(10)}\n";
byte[] bytes = Encoding.UTF8.GetBytes(s);
fs.Write(bytes, 0, bytes.Length);
fs.Close();
fs.Dispose();
}
});
}
Task.WaitAll(tasks);
Console.WriteLine("Program ended");
}
}
}