Coordinate two threads using Monitor
using System;
using System.Threading;
public class MainClass
{
static private int counter = 0;
static private object theLock = new Object();
static private void ThreadFunc1() {
lock( theLock ) {
for( int i = 0; i < 50; ++i ) {
Monitor.Wait( theLock, Timeout.Infinite );
Console.WriteLine( "{0} from Thread {1}", ++counter, Thread.CurrentThread.GetHashCode() );
Monitor.Pulse( theLock );
}
}
}
static private void ThreadFunc2() {
lock( theLock ) {
for( int i = 0; i < 50; ++i ) {
Monitor.Pulse( theLock );
Monitor.Wait( theLock, Timeout.Infinite );
Console.WriteLine( "{0} from Thread {1}", ++counter, Thread.CurrentThread.GetHashCode() );
}
}
}
static void Main() {
Thread thread1 = new Thread( new ThreadStart(ThreadFunc1) );
Thread thread2 = new Thread( new ThreadStart(ThreadFunc2) );
thread1.Start();
thread2.Start();
}
}
1 from Thread 3
2 from Thread 4
3 from Thread 3
4 from Thread 4
5 from Thread 3
6 from Thread 4
7 from Thread 3
8 from Thread 4
9 from Thread 3
10 from Thread 4
11 from Thread 3
12 from Thread 4
13 from Thread 3
14 from Thread 4
15 from Thread 3
16 from Thread 4
17 from Thread 3
18 from Thread 4
19 from Thread 3
20 from Thread 4
21 from Thread 3
22 from Thread 4
23 from Thread 3
24 from Thread 4
25 from Thread 3
26 from Thread 4
27 from Thread 3
28 from Thread 4
29 from Thread 3
30 from Thread 4
31 from Thread 3
32 from Thread 4
33 from Thread 3
34 from Thread 4
35 from Thread 3
36 from Thread 4
37 from Thread 3
38 from Thread 4
39 from Thread 3
40 from Thread 4
41 from Thread 3
42 from Thread 4
43 from Thread 3
44 from Thread 4
45 from Thread 3
46 from Thread 4
47 from Thread 3
48 from Thread 4
49 from Thread 3
50 from Thread 4
51 from Thread 3
52 from Thread 4
53 from Thread 3
54 from Thread 4
55 from Thread 3
56 from Thread 4
57 from Thread 3
58 from Thread 4
59 from Thread 3
60 from Thread 4
61 from Thread 3
62 from Thread 4
63 from Thread 3
64 from Thread 4
65 from Thread 3
66 from Thread 4
67 from Thread 3
68 from Thread 4
69 from Thread 3
70 from Thread 4
71 from Thread 3
72 from Thread 4
73 from Thread 3
74 from Thread 4
75 from Thread 3
76 from Thread 4
77 from Thread 3
78 from Thread 4
79 from Thread 3
80 from Thread 4
81 from Thread 3
82 from Thread 4
83 from Thread 3
84 from Thread 4
85 from Thread 3
86 from Thread 4
87 from Thread 3
88 from Thread 4
89 from Thread 3
90 from Thread 4
91 from Thread 3
92 from Thread 4
93 from Thread 3
94 from Thread 4
95 from Thread 3
96 from Thread 4
97 from Thread 3
98 from Thread 4
99 from Thread 3
100 from Thread 4
Increment Monitor
using System;
using System.Threading;
public class MainClass
{
private static Object locker = new Object();
private static int count = 0;
public int IncrementCount()
{
int rc;
lock( locker )
{
rc = ++count;
}
return rc;
}
public void DoCount()
{
for( int i = 0; i < 10; i++ )
{
System.Console.WriteLine( "Thread {0}: count = {1}", Thread.CurrentThread.Name, IncrementCount() );
Thread.Sleep( 0 );
}
}
[STAThread]
static void Main(string[] args)
{
int limit = 10;
Thread[] t = new Thread[ limit ];
for(int k = 0; k < limit; k++ )
{
MainClass b = new MainClass();
t[ k ] = new Thread( new ThreadStart( b.DoCount ) );
t[ k ].Name = "Thread " + k;
}
for(int k = 0; k < limit; k++ )
{
t[ k ].Start();
}
for(int k = 0; k < limit; k++ )
{
t[ k ].Join();
}
System.Console.WriteLine( "All threads complete" );
}
}
Monitor: Enter and Exit
using System;
using System.Threading;
class MainClass
{
[STAThread]
static void Main(string[] args)
{
int r = 0;
object t = new object();
try
{
Monitor.Enter( t );
r++;
}
finally
{
Monitor.Exit( t );
}
}
}
in monotor
in monotor
Monitor Pool
using System;
using System.Threading;
class MainClass
{
private const int threads = 4;
private const int workitems = 50;
private static Object locker = new Object();
static void Worker()
{
while( true )
{
lock( locker )
{
Monitor.Wait( locker );
}
System.Console.WriteLine( "{0} doing work", 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 = "Worker " + k;
t[ k ].IsBackground = true;
t[ k ].Start();
}
for( int i = 0; i < workitems; i ++ )
{
Thread.Sleep( 1000 );
lock( locker )
{
Monitor.Pulse( locker );
}
}
}
}
Monitor: try to enter
using System;
using System.Threading;
class MainClass
{
[STAThread]
static void Main(string[] args)
{
object t = new object();
int r = 0;
try
{
if ( Monitor.TryEnter( t, 250 ) )
{
r++;
}
}
finally
{
try
{
Monitor.Exit( t );
}
catch( SynchronizationLockException sle )
{
Console.WriteLine(sle);
}
}
}
}
Throw exception between Monitor.Enter and Montor.Exit
using System;
using System.Threading;
class Database
{
public void SaveData(string text)
{
Console.WriteLine("[SaveData] Started");
Monitor.Enter(this);
Console.WriteLine("[SaveData] Working");
throw new Exception("ERROR!");
for (int i = 0; i < 50; i++)
{
Thread.Sleep(100);
Console.Write(text);
}
Monitor.Exit(this);
Console.WriteLine("\n[SaveData] Ended");
}
}
class ThreadMonitor3App
{
public static Database db = new Database();
public static void WorkerThreadMethod1()
{
Console.WriteLine("[WorkerThreadMethod1] Started");
Console.WriteLine("[WorkerThreadMethod1] " +
"Calling Database.SaveData");
try
{
db.SaveData("x");
}
catch{}
Console.WriteLine("[WorkerThreadMethod1] Finished");
}
public static void WorkerThreadMethod2()
{
Console.WriteLine("[WorkerThreadMethod2] Started");
Console.WriteLine("[WorkerThreadMethod2] " +
"Calling Database.SaveData");
try
{
db.SaveData("o");
}
catch{}
Console.WriteLine("[WorkerThreadMethod2] Finished");
}
public static void Main()
{
ThreadStart worker1 = new ThreadStart(WorkerThreadMethod1);
ThreadStart worker2 = new ThreadStart(WorkerThreadMethod2);
Thread t1 = new Thread(worker1);
Thread t2 = new Thread(worker2);
t1.Start();
t2.Start();
Console.ReadLine();
}
}
Use Monitors
using System;
using System.Collections;
using System.Threading;
class MainClass
{
public static ArrayList MyList = new ArrayList();
static void Main(string[] args)
{
Thread ThreadOne = new Thread(new ThreadStart(MonitorExample));
ThreadOne.Start();
}
static void MonitorExample()
{
Monitor.Enter(MyList);
MyList.Add("a value");
Monitor.Exit(MyList);
}
}
Use Monitor to control more than one Threads
using System;
using System.Threading;
class MyClass
{
private int counter;
public void DoSomeWork()
{
lock(this)
{
counter++;
// Do the work.
for(int i = 0; i < 5; i++)
{
Console.WriteLine("counter: {0}, i: {1}, current thread: {2}",
counter, i, Thread.CurrentThread.Name);
Thread.Sleep(1000);
}
}
}
}
public class MainClass
{
public static int Main(string[] args)
{
MyClass w = new MyClass();
Thread workerThreadA = new Thread(new ThreadStart(w.DoSomeWork));
workerThreadA.Name = "A";
Thread workerThreadB = new Thread(new ThreadStart(w.DoSomeWork));
workerThreadB.Name = "B";
Thread workerThreadC = new Thread(new ThreadStart(w.DoSomeWork));
workerThreadC.Name = "C";
// Now start each one.
workerThreadA.Start();
workerThreadB.Start();
workerThreadC.Start();
return 0;
}
}
counter: 1, i: 0, current thread: A
counter: 1, i: 1, current thread: A
counter: 1, i: 2, current thread: A
counter: 1, i: 3, current thread: A
counter: 1, i: 4, current thread: A
counter: 2, i: 0, current thread: B
counter: 2, i: 1, current thread: B
counter: 2, i: 2, current thread: B
counter: 2, i: 3, current thread: B
counter: 2, i: 4, current thread: B
counter: 3, i: 0, current thread: C
counter: 3, i: 1, current thread: C
counter: 3, i: 2, current thread: C
counter: 3, i: 3, current thread: C
counter: 3, i: 4, current thread: C
Use Wait() and Pulse() to create a ticking clock
//C# 2.0 The Complete Reference
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(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");
}
}
Tick Tock
Tick Tock
Tick Tock
Tick Tock
Tick Tock
Clock Stopped
Using A Monitor
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
class Tester
{
static long counter = 0;
//new Tester();
static void Main()
{
Thread[] myThreads = {
new Thread( new ThreadStart(Decrementer) ),
new Thread( new ThreadStart(Incrementer) )
};
int ctr = 1;
foreach (Thread myThread in myThreads)
{
myThread.IsBackground = true;
myThread.Start();
myThread.Name = "Thread" + ctr.ToString();
ctr++;
Console.WriteLine("Started thread {0}", myThread.Name);
Thread.Sleep(50);
}
foreach (Thread myThread in myThreads)
{
myThread.Join();
}
}
static void Decrementer()
{
try
{
Monitor.Enter(counter);
if (counter < 10)
{
Console.WriteLine(Thread.CurrentThread.Name);
Console.WriteLine(counter);
Monitor.Wait(counter);
}
while (counter > 0)
{
long temp = counter;
temp--;
Thread.Sleep(1);
counter = temp;
Console.WriteLine(Thread.CurrentThread.Name);
Console.WriteLine(counter);
}
}
finally
{
Monitor.Exit(counter);
}
}
static void Incrementer()
{
try
{
Monitor.Enter(counter);
while (counter < 10)
{
long temp = counter;
temp++;
Thread.Sleep(1);
counter = temp;
Console.WriteLine(Thread.CurrentThread.Name);
Console.WriteLine(counter);
}
Monitor.Pulse(counter);
}
finally
{
Monitor.Exit(counter);
}
}
}