Csharp/CSharp Tutorial/Thread/Monitor
Содержание
- 1 Coordinate two threads using Monitor
- 2 Increment Monitor
- 3 Monitor: Enter and Exit
- 4 Monitor Pool
- 5 Monitor: try to enter
- 6 Throw exception between Monitor.Enter and Montor.Exit
- 7 Use Monitors
- 8 Use Monitor to control more than one Threads
- 9 Use Wait() and Pulse() to create a ticking clock
- 10 Using A Monitor
Coordinate two threads using Monitor
<source lang="csharp">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(); }
}</source>
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
<source lang="csharp">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" ); }
}</source>
Monitor: Enter and Exit
<source lang="csharp">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 ); } }
}</source>
in monotor in monotor
Monitor Pool
<source lang="csharp">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 ); } } }
}</source>
Monitor: try to enter
<source lang="csharp">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); } } }
}</source>
Throw exception between Monitor.Enter and Montor.Exit
<source lang="csharp">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(); }
}</source>
Use Monitors
<source lang="csharp">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); }
}</source>
Use Monitor to control more than one Threads
<source lang="csharp">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; }
}</source>
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
<source lang="csharp">//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"); }
}</source>
Tick Tock Tick Tock Tick Tock Tick Tock Tick Tock Clock Stopped
Using A Monitor
<source lang="csharp">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); } }
}</source>