C# Tutorials and offshore development in India
    Tutorials   Resources   Forum   Communities   Interview   Jobs   Projects   Offshore Development    
Silverlight Tutorials | Mentor | Code Converter | Articles | Code Factory | Computer Jokes | Members | Peer Appraisal | IT Companies | Bookmarks | Revenue Sharing |


Prizes & Awards
My Profile



Active Members
TodayLast 7 Days more...

New Feature: Community Sites: Create your own .NET community website and start earning from Google AdSense ! It's Free !




Thread Synchronization


Posted Date: 23 Mar 2007    Resource Type: Code Snippets    Category: Threading

Posted By: Prajnan Das       Member Level: Gold
Rating:     Points: 10



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.



Responses


No responses found. Be the first to respond and make money from revenue sharing program.

Feedbacks      
Popular Tags   What are tags ?   Search Tags  
(No tags found.)

Post Feedback


This is a strictly moderated forum. Only approved messages will appear in the site. Please use 'Spell Check' in Google toolbar before you submit.
You must Sign In to post a response.
Next Resource: Prevent sharing of static fields across instances/threads
Previous Resource: Lock a single variable in multi-threaded applications
Return to Discussion Resource Index
Post New Resource
Category: Threading


Post resources and earn money!
 
Related Resources



dotNet Slackers   BizTalk Adaptors    Web Design

teleconferencing service

Contact Us    Privacy Policy    Terms Of Use