This is a contrived example of threads and locking in C#. Basically what it does is start 10 threads, and each one is responsible for incrementing a shared value a large number of times. The increment is done in a non-atomic way:
long val = amount+1;
amount = val;
If it was done in an atomic way (eg ++amount) then this example wouldn't work. The point of all this is that if a thread gets interrupted between the two lines above, then 'amount' gets messed up. Like this (again, contrived) example: amount starts off = 100 Thread 1: val = amount + 1 (101) Thread 2 butts in for a few loops: val = amount + 1 (101) amount = val (101) ... repeat the above 2 lines 50 times ... ends up with amount = 150 Thread 1 resumes: amount = val (101) (overwriting the 50 increments from thread #2) I've got a commented-out 'lock' around the incrementer. If you un-comment it, then everything just works. The 2-line increments can still get barged in on, but the thread that interrupts it can't lock the 'amount' variable, because its already locked, so it waits... and the CPU scheduler passes control back to the thread that was so rudely interrupted. Think of a lock as a 'talking stick' - only one person can grab it at once. Anyway, here's the example. Also you may notice that i'm using a lock on a 'pause' object. This is ancillary - it's to ensure that all the threads kick off at the same exact time.
using System;
using System.Threading;

namespace ThreadTest
{
  class Program
  {
    static object pause = new object();
    static object amountlock = new object();
    static long amount = 0;
    static long count = 10000000;

    static void MyThread()
    {
      // Wait until we can go
      lock (pause) { }
      // Add to the amount
      for (int i = 0; i < count; i++)
      {
        //lock (amountlock) // Uncomment this to see what difference it makes
        {
          long val = amount+1;
          amount = val;
        }
      }
    }

    static void Main(string[] args)
    {
      Thread[] threads = new Thread[10];

      // Start the threads
      lock (pause) // lock them so they start simultaneously
      {
        for (int i = 0; i < threads.Length; i++)
        {
          threads[i] = new Thread(new ThreadStart(MyThread));
          threads[i].Start();
        }
      }

      // Wait for them all to finish
      for (int i = 0; i < threads.Length; i++)
        threads[i].Join();

      // Done
      Console.WriteLine("Total sum: {0} (should be {1})", amount, count * threads.Length);
    }
  }
}

Thanks for reading! And if you want to get in touch, I'd love to hear from you: chris.hulbert at gmail.

Chris Hulbert

(Comp Sci, Hons - UTS)

Software Developer (Freelancer / Contractor) in Australia.

I have worked at places such as Google, Cochlear, Assembly Payments, News Corp, Fox Sports, NineMSN, FetchTV, Coles, Woolworths, Trust Bank, and Westpac, among others. If you're looking for help developing an iOS app, drop me a line!

Get in touch:
[email protected]
github.com/chrishulbert
linkedin



 Subscribe via RSS