static void Main(string[] args) { var tasks = new List <Task>(); var ba = new BankAccount(); for (int i = 0; i < 10; ++i) { tasks.Add(Task.Factory.StartNew(() => { for (int j = 0; j < 1000; ++j) { ba.Deposit(100); } })); tasks.Add(Task.Factory.StartNew(() => { for (int j = 0; j < 1000; ++j) { ba.Withdraw(100); } })); } Task.WaitAll(tasks.ToArray()); Console.WriteLine($"Final balance is {ba.Balance}."); // show interlocked methods here // Interlocked.MemoryBarrier is a wrapper for Thread.MemoryBarrier // only required on memory systems that have weak memory ordering (e.g., Itanium) // prevents the CPU from reordering the instructions such that those before the barrier // execute after those after Console.WriteLine("All done here."); }
public static void SpinLockDemo() { var tasks = new List <Task>(); var ba = new BankAccount(); // spinning avoid overhead of resheduling // useful if you expect the wait time to be very short SpinLock sl = new SpinLock(); // owner tracking keeps a record of which thread acquired it to improve debugging for (int i = 0; i < 10; ++i) { tasks.Add(Task.Factory.StartNew(() => { for (int j = 0; j < 1000; ++j) { bool lockTaken = false; try { // sl.IsHeld // sl.IsHeldByCurrentThread sl.Enter(ref lockTaken); ba.Deposit(100); } finally { if (lockTaken) { sl.Exit(); } } } })); tasks.Add(Task.Factory.StartNew(() => { for (int j = 0; j < 1000; ++j) { bool 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}."); }