Threading with Monitor

A monitor is a mechanism for ensuring that only one thread at a time may be running a certain piece of code (critical section). A monitor has a lock, and only one thread at a time may acquire it. To run in certain blocks of code, a thread must have acquired the monitor. A monitor is always associated with a specific object and cannot be dissociated from or replaced within that object.

Monitor has the following features:

The following information is maintained for each synchronized object:

Monitor Class

The Monitor Class Provides a mechanism that synchronizes access to objects. The Monitor class is a collection of static methods that provides access to the monitor associated with a particular object, which is specified through the method's first argument. the class provide following method.

In the following example we have three threads which are trying to write a file (akshay.txt). Basically each thread will wait until the locker object gets released by the first thread that achieved a lock, before it attempts to write to our file.

using System;
using System.IO;
using System.Threading;
namespace monitorclass
{
class Program
{
static object locker = new object();
static void ThreadMain()
{
Thread.Sleep(800);
// Simulate Some work
WriteToFile(); // Access a shared resource / critical section
}
static void WriteToFile()
{
String ThreadName = Thread.CurrentThread.Name;
Console.WriteLine("{0} using C-sharpcorner.com", ThreadName);
Monitor.Enter(locker);
try

{
using (StreamWriter sw = new StreamWriter(@"D:\akshaydata\akshay.txt", true))
{
sw.WriteLine(ThreadName);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
Monitor.Exit(locker);
Console.WriteLine("{0} releasing C-sharpcorner.com", ThreadName);
}
}
static void Main(string[] args)
{
for (int i = 0; i < 3; i++)

{
Thread thread = new Thread(new ThreadStart(ThreadMain));
thread.Name = String.Concat("Thread - ", i);
thread.Start();

}
Console.Read();
}
}
}

Output

1.gif

Use Wait() and Pulse() to create a ticking clock

Monitor.Wait() is used to Releases the lock on an object in order to permit other threads to lock and access the object. The calling thread waits while another thread accesses the object. Pulse signals are used to notify waiting threads about changes to an object's state.

using System;
using System.Threading;
namespace waitndpulesmethod
{
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(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");
Console.Read();
}
}
}

Output

2.gif

Monitor Pool

A thread pool is a collection of threads that can be used to perform a number of tasks in the background. Thread pools are often employed in server applications. Each incoming request is assigned to a thread from the thread pool. Once a thread in the pool completes its task, it is returned to a queue of waiting threads, where it can be reused. This reuse enables applications to avoid the cost of creating a new thread for each task.

using System;
using System.Threading;
namespace monitorpool
{
class Akshay
{
private const int threads = 3;
private const int workitems = 20;
private static Object locker = new Object();
static void Worker()
{
while (true)
{
lock (locker)
{
Monitor.Wait(locker);
}
System.Console.WriteLine("{0} access the website c-sharpcorner", Thread.CurrentThread.Name);
Thread.Sleep(100);
}
}
[STAThread]
static void Main(string[] args)
{
Thread[] t = new Thread[threads];
for (int k = 0; k < threads; k++)
{
t[k] = new Thread(new ThreadStart(Worker));
t[k].Name = "user " + k;
t[k].IsBackground = true;
t[k].Start();
}
for (int i = 0; i < workitems; i++)
{
Thread.Sleep(1000);
lock (locker)
{
Monitor.Pulse(locker);
}
}
Console.Read();
}
}
}

Output

3.gif