Thread Synchronization


In this article we learn about Thread Synchronization and how to how many threads are woken up: Pulse only wakes up a single waiting thread.

The Monitor methods Wait, Pulse and PulseAll go together. They're used to signal between threads. The idea is that one thread calls Wait, which makes it block until another thread calls Pulse or PulseAll. The difference between Pulse and PulseAll is how many threads are woken up: Pulse only wakes up a single waiting thread; PulseAll wakes up all threads waiting on that monitor. In order to call any of these three methods, the thread has to own the monitor of the object reference it passes in as a parameter. When calling Wait, the monitor is released, but then needs to be reacquired before the thread will actually run.

Presented here is an example of resource grabbing competition by two Threads of different priorities. The ResourceAllocator class defines two methods Allocate and Grab. The class uses an internal queue as an storage for integers. The Allocate method en-queues an object into the queue while the Grab method de-queues it. The Grab method waits using Monitor.Wait until there is something to consume from the queue. While the Allocate method calls Monitor.PulseAll to wake up all the threads waiting to consume the integers. The StartCompetition method starts the Allocation in a loop and also spawns two grabber threads of Highest and Lowest Thread priorities.


using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace ClassLibrary
{
public class ResourceAllocator
{
Queue queue = new Queue();
//a common lock is required:
object objLock = new object();
SortedDictionary counts = new SortedDictionary();
bool isOver;

void Allocate(object obj)
{
lock (objLock)
{
queue.Enqueue(obj);
Monitor.PulseAll(objLock);
}
}

object Grab()
{
lock (objLock)
{
while (queue.Count == 0)
{
Monitor.Wait(objLock);
}

return queue.Dequeue();
}
}

public void StartCompetition()
{
//Resource Grabber Threads:
Thread competitor1 = new Thread(new ThreadStart(delegate { StartGrabberJob("competitor1"); }));
Thread competitor2 = new Thread(new ThreadStart(delegate { StartGrabberJob("competitor2"); }));
counts.Add("competitor1", 0);
counts.Add("competitor2", 0);
competitor1.Priority = ThreadPriority.Highest;
competitor2.Priority = ThreadPriority.Lowest;
competitor2.Start();
competitor1.Start();

//Start the Resource Allocation for 100 times:
Random random = new Random(0);
for (int i = 0; i < 100; i++)
{
Console.WriteLine("Resource Allocated {0}", i);
Allocate(i);
Thread.Sleep(random.Next(1000));
}

while (queue.Count != 0)//wait until all resources are grabbed
{
}

isOver = true; //allocation is over

//Since grab jobs are checking for queue.Count == 0; there are possibilities
//of infinite wait once there is nothing to grab.
//So abort the threads running the grab jobs
competitor1.Abort();
competitor2.Abort();

//display the statistics
Console.WriteLine("***End of Competition***");
int cn1 = counts["competitor1"];
int cn2 = counts["competitor2"];
Console.WriteLine("% of grabs by {0} = {1}", "competitor1", Convert.ToDouble(cn1 * 100) / (cn1 + cn2));
Console.WriteLine("% of grabs by {0} = {1}", "competitor2", Convert.ToDouble(cn2 * 100) / (cn1 + cn2));
}

void StartGrabberJob(string tag)
{
Random random = new Random(1);

while (!isOver)
{
object obj = Grab();
Console.WriteLine("\t\t\t\tResource {0} Grabbed by {1}", obj, tag);
counts[tag] = ++counts[tag];
Thread.Sleep(random.Next(1000));
}
}
}
}

Here is how you would start the competition:

new ResourceAllocator().StartCompetition();

I had ran this example multiple times and seen that the high priority thread on average acquires 60% of the integers. While if I make priorities equal I can see the difference narrowing and an almost 50% spilt.


Comments

No responses found. Be the first to comment...


  • Do not include your name, "with regards" etc in the comment. Write detailed comment, relevant to the topic.
  • No HTML formatting and links to other web sites are allowed.
  • This is a strictly moderated site. Absolutely no spam allowed.
  • Name:
    Email: