Sleeping Barber – C#

The sleeping barber is one of the problems which is used to demonstrate the correct thread notification mechanism. Here’s the a sample code for the sleeping barber problem in C# for .NET 4.0. Keep in mind that this code is optimized for the .NET 4.0 not for prior versions. You have concurrent collections in .NET 4.0.

 

using System;
using System.Threading;
using System.Collections.Concurrent;
using Microsoft.ConcurrencyVisualizer.Instrumentation;

namespace SleepingBarber
{
    class Program
    {
        internal static AutoResetEvent customerEvent = new AutoResetEvent(false);

        // no explict locks needed as it is a ConcurrentQueue > feature in .NET 4.0
        internal static ConcurrentQueue<Customer> queue = new ConcurrentQueue<Customer>();

        static void Main(string[] args)
        {
            Random rand = new Random();

            // make the barber background so the program can exit once the main thread is finished.
            // this does not impact the thread priority.
            new Thread(Barber.CutHair) { IsBackground = true, Name = "Barber" }.Start();

            Thread.Sleep(100);

            Thread.CurrentThread.Name = "Main";
            // creating 25 customers in random order
            for (int i = 0; i <25; i++)
            {
                // temp is used to avoid the captured variable problem
                int temp = i;
                Thread.Sleep(rand.Next(600, 2000));
                Customer c = new Customer() {Name = "Customer " + temp };
                queue.Enqueue(c);

                if (queue.Count == 1)
                {
                    Customer.WakeUpBarber();
                }
            }

            Console.ReadKey();
        }
    }

    class Customer
    {
        public string Name { get; set; }

        internal static void WakeUpBarber()
        {
            Program.customerEvent.Set();
        }
    }

    class Barber
    {
        internal static void CutHair()
        {
            while (!Program.queue.IsEmpty)
            {
                Customer c;

                // time to cut the hair is 1 sec
                Thread.Sleep(1000);

                // after cutting hair barber removes him from the queue
                if (Program.queue.TryDequeue(out c))
                {
                    Console.WriteLine("Done hair cutting to {0}", c.Name);
                }
                else
                {
                    // this will never happen in this scenario as only one barber is here
                    Console.WriteLine(" 😦 customer is not going out ...");
                }
            }

            Console.WriteLine("Going to sleep.... grr...err....");
            GoToSleep();
        }

        private static void GoToSleep()
        {
            using (Markers.EnterSpan("wait start"))
            {
                Program.customerEvent.WaitOne();
                Console.WriteLine("Waking up..Oh ! Customer arrived..");
            }
            CutHair();
        }
    }
}

Advertisement

Concurrent Collections and TPL–.NET 4.0

TPL in .NET 4.0 is a cool thing when programming modern PCs which have CPUs with more than one core. CPUs with many cores are popular these days because hardware vendors make CPUs with many cores to cater the Moore’s Law. 🙂 Or they might have tired of shrinking the transistor size up to 32nm. There are smaller versions than that..

Task Parallel Library’s (TPL’s) Task.Factory.StatNew( () => {..} is the .NET 4.0’s replacement for the Thread.QueueUserWorkItem() and asynchronous delegates. In this case TPL is more close to the asynchronous delegates and also it is documented that; TPL can leverage the underlying CPU cores more effectively than asynchronous delegates.

But in the documentation TPL considered as a library for the parallel programming.

And we also have Concurrent Collections in System.Collections.Concurrent namespace which contains the thread safe versions of the normal collections. So this makes easy that we do not need to handle explicit locks while handling the collections from different threads.

Concurrent Collections are slower compared to normal collections and little different, but thread safe. Even in the documentation and MSDN samples concurrent collections are mentioned in the parallel programming paradigm, not in a multi threaded application’s view.

I had some doubt on this, whether is it OK to use them in multi threaded environment; and raised a question in the MSDN, The thread seems to be useful and interesting.

I didn’t repost the question , answers and the code in my blog, as you can see them here