Csharp/CSharp Tutorial/Thread/Monitor — различия между версиями
Admin (обсуждение | вклад) м (1 версия) |
|
(нет различий)
|
Текущая версия на 12:20, 26 мая 2010
Содержание
- 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
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);
}
}
}