public void TryRaceCondition() { List <Task> tasks = new List <Task>(); BanckAccount account = new BanckAccount(); Enumerable.Range(1, 30).ToList().ForEach(x => tasks.Add(new Task(() => account.Deposit(100)))); Enumerable.Range(1, 30).ToList().ForEach(x => tasks.Add(new Task(() => account.Withdraw(100)))); tasks.ForEach(t => t.Start()); Task.WaitAll(tasks.ToArray()); Console.WriteLine(account.Balance); tasks.Clear(); Enumerable.Range(1, 30).ToList().ForEach(x => tasks.Add(new Task(() => account.DepositInterlock(100)))); Enumerable.Range(1, 30).ToList().ForEach(x => tasks.Add(new Task(() => account.WithdrawInterlock(100)))); tasks.ForEach(t => t.Start()); Task.WaitAll(tasks.ToArray()); Console.WriteLine(account.Balance); }
public void TryMutex() { void Transfer(BanckAccount from, BanckAccount to, int amount) { from.Balance -= amount; to.Balance += amount; } List <Task> tasks = new List <Task>(); BanckAccount account1 = new BanckAccount(); BanckAccount account2 = new BanckAccount(); Mutex mutex1 = new Mutex(); Mutex mutex2 = new Mutex(); tasks.Add(new Task(() => { for (int i = 0; i < 1000; i++) { bool haveLock = mutex1.WaitOne(); try { account1.Balance += 1; } finally { if (haveLock) { mutex1.ReleaseMutex(); } } } })); tasks.Add(new Task(() => { for (int i = 0; i < 1000; i++) { bool haveLock = mutex2.WaitOne(); try { account2.Balance += 1; } finally { if (haveLock) { mutex2.ReleaseMutex(); } } } })); // Transfer needs to lock both accounts Enumerable.Range(1, 10).ToList().ForEach(x => tasks.Add(new Task(() => { bool haveLock = Mutex.WaitAll(new[] { mutex1, mutex2 }); try { Transfer(account1, account2, 100); } finally { if (haveLock) { mutex1.ReleaseMutex(); mutex2.ReleaseMutex(); } } }))); tasks.ForEach(t => t.Start()); Task.WaitAll(tasks.ToArray()); Console.WriteLine(account1.Balance); Console.WriteLine(account2.Balance); }