Multithreading in .NET is made simpler. Reason behind the simplicity is the effective methods designed for thread communication. Monitor class supplies the following methods which are key in thread communication. They areWait (), Pulse (), PulseAll ().
Detailed Analysis
The Wait( ), Pulse( ), and PulseAll( ) methods are defined by the Monitor class. These methods can be called only from within a locked block of code. Here is how they are used. When a thread is temporarily blocked from running, it calls Wait( ).
This causes the thread to go to sleep and the lock for that object to be released, allowing another thread to use the object. At a later point, the sleeping thread is awakened when some other thread enters the same lock and calls Pulse( ) or PulseAll( ).
A call to Pulse( ) resumes the first thread in the queue of threads waiting for the lock. A call to PulseAll( ) signals the release of the lock to all waiting threads.
Commonly used form of Wait() are
public static bool Wait(object waitOb)
public static bool Wait(object waitOb, int milliseconds)
Where waitOb is the object getting released.
Code Sample - Illustration
using System;
using System.Threading;
class TickTock {
public void tick(bool running) {
lock(this) {
if(!running) { // stop the clock
Monitor.Pulse(this); // notify any waiting threads
return;
}
Console.Write("Tick ");
Monitor.Pulse(this); // let tock() run
Monitor.Wait(this); // wait for tock() to complete
}
}
public void tock(bool running) {
lock(this) {
if(!running) { // stop the clock
Monitor.Pulse(this); // notify any waiting threads
return;
}
Console.WriteLine("Tock");
Monitor.Pulse(this); // let tick() run
Monitor.Wait(this); // wait for tick to complete
}
}
}
class MyThread {
public Thread thrd;
TickTock ttOb;
// Construct a new thread.
public MyThread(string name, TickTock tt) {
thrd = new Thread(new ThreadStart(this.run));
ttOb = tt;
thrd.Name = name;
thrd.Start();
}
// Begin execution of new thread.
void run() {
if(thrd.Name == "Tick") {
for(int i=0; i<5; i++) ttOb.tick(true);
ttOb.tick(false);
}
else {
for(int i=0; i<5; i++) ttOb.tock(true);
ttOb.tock(false);
}
}
}
class TickingClock {
public static void Main () {
TickTock tt = new TickTock();
MyThread mt1 = new MyThread("Tick", tt);
MyThread mt2 = new MyThread("Tock", tt);
mt1.thrd.Join();
mt2.thrd.Join();
Console.WriteLine("Clock Stopped");
}
}
Code - Output
Tick Tock
Tick Tock
Tick Tock
Tick Tock
Tick Tock
Clock Stopped
Dead Lock
Deadlock is, as the name implies, a situation in which one thread is waiting for another thread to do something, but that other thread is waiting on the first. Thus, both threads are suspended, waiting for each other, and neither executes. This situation is analogous to two overly polite people both insisting that the other step through a door first!
Avoiding deadlock seems easy, but it's not. For example, deadlock can occur in roundabout ways. Consider the TickTock class. As explained, if a final Pulse( ) is not executed by tick( ) or tock( ), then one or the other will be waiting indefinitely and the program is deadlocked. Often the cause of the deadlock is not readily understood just by looking at the source code to the program, because concurrently executing threads can interact in complex ways.
Happy Learning !