public static void Spin_Locking() { var tasks = new List <Task>(); var ba = new BankAccountV3(0); SpinLock sl = new SpinLock(); for (int i = 0; i < 10; i++) { tasks.Add(Task.Factory.StartNew(() => { for (int j = 0; j < 1000; j++) { // previous examples assumed that lock was always possible to take var lockTaken = false; try { sl.Enter(ref lockTaken); ba.Deposit(100); } finally { if (lockTaken) { sl.Exit(); } } } })); tasks.Add(Task.Factory.StartNew(() => { for (int j = 0; j < 1000; j++) { var lockTaken = false; try { sl.Enter(ref lockTaken); ba.Withdraw(100); } finally { if (lockTaken) { sl.Exit(); } } } })); } Task.WaitAll(tasks.ToArray()); Console.WriteLine($"Final balance is {ba.Balance}"); Console.ReadKey(); }
public void Transfer(BankAccountV3 where, int amount) { where.Balance += amount; Balance -= amount; }
public static void Local_Mutex() { var tasks = new List <Task>(); var ba = new BankAccountV3(0); var ba2 = new BankAccountV3(0); // many synchro types deriving from WaitHandle // Mutex = mutual exclusion // two types of mutexes // this is a _local_ mutex Mutex mutex = new Mutex(); Mutex mutex2 = new Mutex(); for (int i = 0; i < 10; ++i) { tasks.Add(Task.Factory.StartNew(() => { for (int j = 0; j < 1000; ++j) { bool haveLock = mutex.WaitOne(); try { ba.Deposit(1); // deposit 10000 overall } finally { if (haveLock) { mutex.ReleaseMutex(); } } } })); tasks.Add(Task.Factory.StartNew(() => { for (int j = 0; j < 1000; ++j) { bool haveLock = mutex2.WaitOne(); try { ba2.Deposit(1); // deposit 10000 } finally { if (haveLock) { mutex2.ReleaseMutex(); } } } })); // transfer needs to lock both accounts tasks.Add(Task.Factory.StartNew(() => { for (int j = 0; j < 1000; j++) { bool haveLock = Mutex.WaitAll(new[] { mutex, mutex2 }); try { ba.Transfer(ba2, 1); // transfer 10k from ba to ba2 } finally { if (haveLock) { mutex.ReleaseMutex(); mutex2.ReleaseMutex(); } } } })); } Task.WaitAll(tasks.ToArray()); Console.WriteLine($"Final balance is: ba={ba.Balance}, ba2={ba2.Balance}."); }