Click here to Skip to main content
15,867,453 members
Articles / General Programming / Threads
Article

Thread Synchronization with Semaphore

Rate me:
Please Sign up or sign in to vote.
4.00/5 (5 votes)
19 Nov 2011CPOL1 min read 54.8K   1.6K   31   5
An introduction to semaphore in contrast to Monitor
Semaphore.JPG

Introduction

Semaphore is a synchronization technique where we can control number of threads to access a resource. In lock/Mutex, only one thread can access resources at a time. But Semaphore allows multiple threads to access the same resource at a time. We can limit the number of threads that can access the same resources. In this article, I have shown three different ways to access resources.

  • No-1. No Synchronization
  • No-2. Synchronization with Monitor
  • No-3. Synchronization with Semaphore

Using the Code

No Synchronization

With no synchronization, all threads run simultaneously and execute the same piece of code simultaneously. There is no restriction on how many threads can access it. Following is the code:

C#
private void btnNoSync_Click(object sender, EventArgs e)
{
            listBox1.Items.Add("== No Synchronization ===========");
            int TotalThread = 5;
            Thread[] Threads = new Thread[TotalThread];
            for (int i = 0; i < TotalThread; i++)
            {
                Threads[i] = new Thread(new ThreadStart(AccessCode));
                Threads[i].IsBackground = true;
                Threads[i].Start();
            } 
}
public void AccessCode()
{
   listBox1.BeginInvoke(new ParameterizedThreadStart(UpdateUI), new object[] 
       {"Thread ID : " + Thread.CurrentThread.ManagedThreadId.ToString() + ": Entered" }
                        );
   Thread.Sleep(500);
   listBox1.BeginInvoke(new ParameterizedThreadStart(UpdateUI), new object[]  
       { "Thread ID : " + Thread.CurrentThread.ManagedThreadId.ToString() + " : Exit" }
                        );
}
 
// Following code is used to update UI
public void UpdateUI(object objOutput)
{
   listBox1.Items.Add(objOutput.ToString());
}

Synchronization with Monitor

Synchronization with monitor class, only one thread can access the same resource at a time. Thread is run simultaneously but it can access the block of code one at a time. There is a restriction on thread so that only a single thread can access a particular code block.

C#
private void buttonMonitor_Click(object sender, EventArgs e)
{
            listBox1.Items.Add("== Using Monitor =============");
            int TotalThread = 5;
            Thread[] Threads = new Thread[TotalThread];
            for (int i = 0; i < TotalThread; i++)
            {
                Threads[i] = new Thread(new ThreadStart(AccessCodeWithMonitor));
                Threads[i].IsBackground = true;
                Threads[i].Start();
            }
} 
private void AccessCodeWithMonitor()
{
            Monitor.Enter(this);
            try
            {
                listBox1.BeginInvoke(new ParameterizedThreadStart(UpdateUI), new object[] 
                     { "Thread ID : " + 
		    Thread.CurrentThread.ManagedThreadId.ToString() + " : Entered" });
                Thread.Sleep(500);
                listBox1.BeginInvoke(new ParameterizedThreadStart(UpdateUI), new object[] 
                     { "Thread ID : " + 
		    Thread.CurrentThread.ManagedThreadId.ToString() + " : Exit" });
            }
            finally
            {
                Monitor.Exit(this);
            }
}
private void UpdateUI(object objOutput)
{
   listBox1.Items.Add(objOutput.ToString());
}

Synchronization with Semaphore

In synchronization with semaphore class, we can allow more than one thread to access the same block of code. Actually, we can specify how many threads can access the same block of code at the same time.

C#
private void btnSemaphore_Click(object sender, EventArgs e)
{
            listBox1.Items.Add("== Using Semaphore =============");
            int TotalThread = 5;
            int SemaphoreCount = 3;
            Thread[] Threads = new Thread[TotalThread];
            Semaphore Sema = new Semaphore(SemaphoreCount, SemaphoreCount);
            for (int i = 0; i < TotalThread; i++)
            {
                Threads[i] = new Thread(new ParameterizedThreadStart
				(AccessCodewithSemaphore));
                Threads[i].IsBackground = true;
                Threads[i].Start(Sema);
            }
}
public void AccessCodewithSemaphore(object objSemaphore)
{
            bool IsComplete = false;
            Semaphore l_SemaPhore = (Semaphore)objSemaphore;
            while (!IsComplete)
            {
                if (l_SemaPhore.WaitOne(200, false))
                {
                  try
                  {
                    listBox1.BeginInvoke(new ParameterizedThreadStart(UpdateUI), 
					new object[] 
                      {"Thread ID : " + 
		    Thread.CurrentThread.ManagedThreadId.ToString() + " : Entered" });
                    Thread.Sleep(500);
                   }
                   finally
                   {
                     l_SemaPhore.Release();
                     listBox1.BeginInvoke(new ParameterizedThreadStart(UpdateUI), 
					new object[] 
                       { "Thread ID : " + 
		     Thread.CurrentThread.ManagedThreadId.ToString() + " : Exit" });
                     IsComplete = true;
                    }
                }
                else
                {
                  listBox1.BeginInvoke(new ParameterizedThreadStart(UpdateUI), 
					new object[] 
                  {"Thread ID :"+Thread.CurrentThread.ManagedThreadId.ToString() + 
				": Waiting To enter"});
                }
            }
} 
public void UpdateUI(object objOutput)
{
   listBox1.Items.Add(objOutput.ToString());
}

Testing the Code

Semaphore can be tested easily. Run the application and press all buttons one by one and see the effect of semaphore which controls the total number of threads that can execute some block of code simultaneously. Semaphore is a resource based synchronization technique and its system wide synchronization resource.

History

  • 19th November, 2011: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer Sapient Corporation Pvt. Ltd.
India India
Software Devloper sience 2006. Experience on VB 6.0,C# Web, Windows and Distributed application like WCF etc. Currently working at Sapient Corporation Pvt. Ltd

Comments and Discussions

 
QuestionMonitor.Wait and Monitor.Pulse Pin
supercat921-Nov-11 12:09
supercat921-Nov-11 12:09 
QuestionWhen one should use a semaphore? Pin
Paulo Zemek21-Nov-11 1:10
mvaPaulo Zemek21-Nov-11 1:10 
I think the big question here is: When one needs to use a semaphore?

In fact, you compared a semaphore to a lock, but their purpose is very different.
Even if you can compare a lock as a semaphore that allows only one at a time, the lock exists to avoid that "incomplete" states are seen by other threads.
A very simple example can be shown by drawing lines to the screen using the old "MoveTo" and "DrawTo" functions.
If one thread does MoveTo 0, 0 and DrawTo 100, 0
While another one does MoveTo 0, 100 and DrawTo 100, 100 without synchronization, we may end up doing:
MoveTo 0, 0 - useless
MoveTo 0, 100
DrawTo 100, 0
DrawTo 100, 100

Which will give us a completely wrong result, all because an incomplete state was used. Using a semaphore will not help solve such problem.

So, what's the advantage of a semaphore?
In which cases do you believe one should use a semaphore? If it is not avoiding one thread to see incomplete states... what's its purpose?
I can say that I personally use semaphores to run many animations at once, limiting the amount of simultaneous threads to the number of processors... after all, having more threads running at the same time will only degrade performance.
Do you want to create a new programming language?
Do you want to know how to create a virtual machine?
Are at least interested on how they work?
So, see my article: POLAR

GeneralMy vote of 3 Pin
Sander Rossel19-Nov-11 3:15
professionalSander Rossel19-Nov-11 3:15 
GeneralRe: My vote of 3 Pin
Pranjit Kalita24-Nov-11 3:53
Pranjit Kalita24-Nov-11 3:53 
GeneralRe: My vote of 3 Pin
Sander Rossel24-Nov-11 7:05
professionalSander Rossel24-Nov-11 7:05 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.