C#, MultiThreading

Producer Consumer Problem using locks in C#.Net

Problem Statement

The Producer Consumer problem is a classical Multithreaded problem which involves synchronization among multiple threads which are producing/consuming items from a resource at different speeds.

There are different ways to solve this problem in C#. I would be using the Monitor class for locking and its Wait/Pulse methods for signalling.

The client of the ProducerConsumer Class could use the old Threading API (Thread class) to spin off threads which try to consume/produce items or use TPL to use threads from the ThreadPool.

Code

using System.Collections.Generic;
using System.Linq;
using System.Threading;
 
namespace MultiThreading
{
    internal class ProducerConsumerProblem
    {
        private readonly object _lock = new object();
        private readonly Queue<int> queue = new Queue<int>();
 
 
        public void Produce(int input)
        {
            lock (_lock)
            {
                queue.Enqueue(input);
                Monitor.Pulse(_lock);
            }
        }
 
        public int Consume()
        {
            lock (_lock)
            {
                while (!queue.Any())
                {
                    Monitor.Wait(_lock);
                }
 
                return queue.Dequeue();
            }
        }
    }
}

Test

 [TestMethod]
       public void PoducerConsumerProblem_Should_Succeed()
       {
           var producerConsumerProblem = new ProducerConsumerProblem();
 
           Thread.CurrentThread.Name = "Main Consumer Thread";
           var t1=new Thread(
             () => producerConsumerProblem.Produce(1)) {Name = "Producer Thread"};
           t1.Start();
 
           producerConsumerProblem.Consume();
         
 
           var t2 =new Thread(
               () =>
               {
                   for (int i = 0; i < 10; i++)
                   {
                       producerConsumerProblem.Produce(i);
                   }
                   
               }
               ) {Name = "Producer Thread 2"};
 
           t2.Start();
       }

Final Words

.NET Framework 4.5 has a Concurrent collection called BlockingCollection which solves the same Producer-Consumer problem. In case you are using a former version of the framework, using Monitor is the simplest way to solve the problem. You can also use Semaphores to restrict Threads to a certain number (maybe depending on the cores of your system).

Standard

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s