Every one knows that when different threads write to the same data structure they need to be synced.

Lets assume we have a Service that exposed a single function Add which added the value received to a List.

   1: public class ListWrapper

   2: {

   3:     private readonly List<int> m_list =new List<int>();


   5:     public void Add(int i)

   6:     {

   7:         m_list.Add(i);

   8:     }

   9: }

In order to make it thread safe we would simply lock the List so if multiple thread try to access this function they will add their values to the list each at a time.

   1: public void Add(int i)

   2: {

   3:     lock (m_list)

   4:     {

   5:         m_list.Add(i);

   6:     }

   7: }

For 99.9% of the applications this is a good solution.

Lets look at the following code:

   1: private static object m_locker = new object();

   2: static void Main(string[] args)

   3: {

   4:     for (int i = 0; i < 50; i++)

   5:     {

   6:         int iLocal = i;

   7:         Task.Factory.StartNew(() =>

   8:                                   {

   9:                                       lock (m_locker)

  10:                                       {

  11:                                           Console.WriteLine(iLocal);

  12:                                       }

  13:                                   });

  14:     }

  15:     Console.ReadLine();

  16: }

What do you think will be printed to the screen? If you though we are going to see the numbers 0-49 in order you are very wrong…

Here is one of the results of running this code:



Look at 3 its almost at the end! while 10-30 are neatly ordered.

This is due to the fact that lock() does not keep order, you never know which thread will get the priority to work.

Now that we know not to count on lock to keep our threads in line there is one more thing to notice here.

This test was with 50 calls. What if this was a web server that handles many calls a second 24/7? Since lock() does not offer any promise of order, there is a chance that some of the threads will stay “stuck” in that lock statement for a long time and possibly forever! In many applications this is not a problem but sometimes it means there is a desperate user on the other side trying to understand what went wrong…

So in conclusion :

  1. Don’t count on the lock() statement to keep your threads in order
  2. The lock() statement is not good enough for heavily multithreaded critical sections.

Did this ever cause any trouble to you? if so please comment.



Tags :

Post a Comment