Uses Wait and Pulse to enable producer and consumer threads to cooperate in using a buffer

image_pdfimage_print
   

/*
Revised from code in "Computing with C# and the .NET Framework"

# Paperback: 753 pages
# Publisher: Jones and Bartlett Publishers, Inc.; Bk&CD-Rom edition (February 2003)
# Language: English
# ISBN: 0763723398
# Product Dimensions: 8.9 x 7.7 x 1.1 inches
*/


using System;
using System.Runtime.CompilerServices;
using System.Threading;  

  class Buffer {
    public const int size = 3;
    int[] buffer = new int [size];             
    int putpos=0;
    int getpos=0;
    int number=0;

    [MethodImpl(MethodImplOptions.Synchronized)]
    public void Put(int value) {
      if (number == size) {
        Console.WriteLine("Cannot put -- Buffer full");
        Monitor.Wait(this);
      }
      number++;
      buffer[putpos] = value;
      Console.WriteLine("Put "+value);
      putpos = (putpos + 1) % size;
      if (number == 1) Monitor.Pulse(this);         
    }

    [MethodImpl(MethodImplOptions.Synchronized)]
    public int Get() {
      if (number == 0) {
         Console.WriteLine("Buffer empty");
         Monitor.Wait(this);
      }
      number--;
      int n = buffer[getpos];
      Console.WriteLine("Get "+n);
      getpos = (getpos + 1) % size;
      if (number == size - 1) Monitor.Pulse(this);    
      return n;
    }
  }
  class Producer {
     Buffer buf;
     public Producer(Buffer b) { 
        buf = b;
        Thread thread = new Thread(new ThreadStart(Run));
        thread.Start();  
     }      
     public void Run() {
       for(; true; ) {
             buf.Put(0);
       }
     }
  }
  class Consumer {
     Buffer buf;
     public Consumer(Buffer b) { 
       buf = b;
       Thread thread = new Thread(new ThreadStart(Run));
       thread.Start();  
     }
     public void Run() {
       for (; true;) {
           buf.Get();
       }
     }
  }

public class PutGet {
  public static void Main(String[] args) {
    Buffer b = new Buffer();
    Producer p = new Producer(b);
    Consumer c = new Consumer(b);
  }
}
           
          


Producer and consumer with a Circular Buffer

image_pdfimage_print

/*
Code revised from Book published by
(C) Copyright 1992-2006 by Deitel & Associates, Inc. and
Pearson Education, Inc. All Rights Reserved.

*/
using System;
using System.Threading;

public class Producer
{
private CircularBuffer sharedLocation;
private Random randomSleepTime;

public Producer( CircularBuffer shared, Random random )
{
sharedLocation = shared;
randomSleepTime = random;
}
public void Produce()
{
for ( int count = 1; count <= 10; count++ ) { Thread.Sleep( randomSleepTime.Next( 1, 3001 ) ); sharedLocation.Buffer = count; } Console.WriteLine( "{0} done producing. Terminating {0}.", Thread.CurrentThread.Name ); } } public class Consumer { private CircularBuffer sharedLocation; private Random randomSleepTime; public Consumer( CircularBuffer shared, Random random ) { sharedLocation = shared; randomSleepTime = random; } public void Consume() { int sum = 0; for ( int count = 1; count <= 10; count++ ) { Thread.Sleep( randomSleepTime.Next( 1, 3001 ) ); sum += sharedLocation.Buffer; } Console.WriteLine("{0} read values totaling: {1}. Terminating {0}.", Thread.CurrentThread.Name, sum ); } } public class CircularBuffer { private int[] buffers = { -1, -1, -1 }; private int occupiedBufferCount = 0; private int readLocation = 0; private int writeLocation = 0; public int Buffer { get { lock ( this ) { if ( occupiedBufferCount == 0 ) { Console.Write( " All buffers empty. {0} waits.",Thread.CurrentThread.Name ); Monitor.Wait( this ); } int readValue = buffers[ readLocation ]; Console.Write( " {0} reads {1} ",Thread.CurrentThread.Name, buffers[ readLocation ] ); --occupiedBufferCount; readLocation = ( readLocation + 1 ) % buffers.Length; Console.Write( CreateStateOutput() ); Monitor.Pulse( this ); return readValue; } } set { lock ( this ) { if ( occupiedBufferCount == buffers.Length ) { Console.Write( " All buffers full. {0} waits.",Thread.CurrentThread.Name ); Monitor.Wait( this ); } buffers[ writeLocation ] = value; Console.Write( " {0} writes {1} ",Thread.CurrentThread.Name, buffers[ writeLocation ] ); ++occupiedBufferCount; writeLocation = ( writeLocation + 1 ) % buffers.Length; Console.Write( CreateStateOutput() ); Monitor.Pulse( this ); } } } public string CreateStateOutput() { string output = "(buffers occupied: " + occupiedBufferCount + ") buffers: "; for ( int i = 0; i < buffers.Length; i++ ) output += " " + string.Format( "{0,2}", buffers[ i ] ) + " "; output += " "; output += " "; for ( int i = 0; i < buffers.Length; i++ ) output += "---- "; output += " "; output += " "; for ( int i = 0; i < buffers.Length; i++ ) { if ( i == writeLocation && writeLocation == readLocation ) output += " WR "; else if ( i == writeLocation ) output += " W "; else if ( i == readLocation ) output += " R "; else output += " "; } output += " "; return output; } static void Main( string[] args ) { CircularBuffer shared = new CircularBuffer(); Random random = new Random(); Console.Write( shared.CreateStateOutput() ); Producer producer = new Producer( shared, random ); Consumer consumer = new Consumer( shared, random ); Thread producerThread = new Thread( new ThreadStart( producer.Produce ) ); producerThread.Name = "Producer"; Thread consumerThread = new Thread( new ThreadStart( consumer.Consume ) ); consumerThread.Name = "Consumer"; producerThread.Start(); consumerThread.Start(); } } [/csharp]

Producer and comsumer in a synchronized buffer

image_pdfimage_print

/*
Code revised from Book published by
(C) Copyright 1992-2006 by Deitel & Associates, Inc. and
Pearson Education, Inc. All Rights Reserved.

*/

using System;
using System.Threading;

public class SynchronizedBuffer
{
private int buffer = -1;

private int occupiedBufferCount = 0;

public int Buffer
{
get
{
Monitor.Enter( this );

if ( occupiedBufferCount == 0 )
{
Console.WriteLine(Thread.CurrentThread.Name + ” tries to read.” );
DisplayState( “Buffer empty. ” +Thread.CurrentThread.Name + ” waits.” );
Monitor.Wait( this );
}
–occupiedBufferCount;

DisplayState( Thread.CurrentThread.Name + ” reads ” + buffer );

Monitor.Pulse( this );
int bufferCopy = buffer;

Monitor.Exit( this );

return bufferCopy;
}
set
{
Monitor.Enter( this );
if ( occupiedBufferCount == 1 )
{
Console.WriteLine(Thread.CurrentThread.Name + ” tries to write.” );
DisplayState( “Buffer full. ” + Thread.CurrentThread.Name + ” waits.” );
Monitor.Wait( this );
}
buffer = value;

++occupiedBufferCount;

DisplayState( Thread.CurrentThread.Name + ” writes ” + buffer );
Monitor.Pulse( this );

Monitor.Exit( this );
}
}

public void DisplayState( string operation )
{
Console.WriteLine( “{0,-35}{1,-9}{2}
“,operation, buffer, occupiedBufferCount );
}

static void Main( string[] args )
{
SynchronizedBuffer shared = new SynchronizedBuffer();
Random random = new Random();

Console.WriteLine( “{0,-35}{1,-9}{2}
“,”Operation”, “Buffer”, “Occupied Count” );
shared.DisplayState( “Initial state” );

Producer producer = new Producer( shared, random );
Consumer consumer = new Consumer( shared, random );

Thread producerThread = new Thread( new ThreadStart( producer.Produce ) );
producerThread.Name = “Producer”;

Thread consumerThread = new Thread( new ThreadStart( consumer.Consume ) );
consumerThread.Name = “Consumer”;

producerThread.Start();
consumerThread.Start();
}
}

public class Consumer
{
private SynchronizedBuffer sharedLocation;
private Random randomSleepTime;

public Consumer( SynchronizedBuffer shared, Random random )
{
sharedLocation = shared;
randomSleepTime = random;
}

public void Consume()
{
int sum = 0;

for ( int count = 1; count <= 10; count++ ) { Thread.Sleep( randomSleepTime.Next( 1, 1001 ) ); sum += sharedLocation.Buffer; } Console.WriteLine("{0} read values totaling: {1}. Terminating {0}.",Thread.CurrentThread.Name, sum ); } } public class Producer { private SynchronizedBuffer sharedLocation; private Random randomSleepTime; public Producer( SynchronizedBuffer shared, Random random ) { sharedLocation = shared; randomSleepTime = random; } public void Produce() { for ( int count = 1; count <= 10; count++ ) { Thread.Sleep( randomSleepTime.Next( 1, 1001 ) ); sharedLocation.Buffer = count; } Console.WriteLine( "{0} done producing. Terminating {0}.",Thread.CurrentThread.Name ); } } [/csharp]

new Mutex(false), WaitOne

image_pdfimage_print

using System;
using System.Threading;

class Database
{
static Mutex mutex = new Mutex(false);

public static void SaveData(string text)
{
mutex.WaitOne();
Console.WriteLine(“Database.SaveData – Started”);
Console.WriteLine(“Database.SaveData – Working”);
for (int i = 0; i < 100; i++) { Console.Write(text); } Console.WriteLine(" Database.SaveData - Ended"); mutex.Close(); } } class ThreadMutexApp{ public static void WorkerThreadMethod1() { Console.WriteLine("Worker thread #1 - Started"); Database.SaveData("x"); Console.WriteLine("Worker thread #1 - Returned from Output"); } public static void WorkerThreadMethod2() { Console.WriteLine("Worker thread #2 - Started"); Database.SaveData("o"); Console.WriteLine("Worker thread #2 - Returned from Output"); } public static void Main() { ThreadStart worker1 = new ThreadStart(WorkerThreadMethod1); ThreadStart worker2 = new ThreadStart(WorkerThreadMethod2); Console.WriteLine("Main - Creating worker threads"); Thread t1 = new Thread(worker1); Thread t2 = new Thread(worker2); t1.Start(); t2.Start(); Console.ReadLine(); } } [/csharp]

new Mutex

image_pdfimage_print
   
 


using System;
using System.Threading;


class NETMutex {
    static Mutex myMutex;

    public static void Main() {
        myMutex = new Mutex(true, "AAA");
        NETMutex nm = new NETMutex();
        Thread t = new Thread(new ThreadStart(nm.Run));
        t.Start();
        Thread.Sleep(5000);
        myMutex.ReleaseMutex();
        myMutex.WaitOne();
    }

    public void Run() {
        Console.WriteLine("In Run");
        myMutex.WaitOne();
        Console.WriteLine("Thread sleeping for 10 secs");
        Thread.Sleep(10000);
        Console.WriteLine("End of Run() method");
    }
}

    


Monitor.Pulse

image_pdfimage_print
   
 

using System;
using System.Threading;

class MessageBoard {
    private String messages = "no messages";

    public void Reader() {
        try {
            Monitor.Enter(this);
            if (messages == "no messages") {
                Console.WriteLine("{0} {1}",Thread.CurrentThread.Name, messages);
                Console.WriteLine("{0} waiting",Thread.CurrentThread.Name);
                Monitor.Wait(this);
            }
            Console.WriteLine("{0} {1}",Thread.CurrentThread.Name, messages);
        } finally {
            Monitor.Exit(this);
        }
    }

    public void Writer() {
        try {
            Monitor.Enter(this);
            messages = "Greetings!";
            Console.WriteLine("{0} Done writing message",Thread.CurrentThread.Name);
            Monitor.Pulse(this);
        } finally {
            Monitor.Exit(this);
        }
    }

    public static void Main() {
        MessageBoard myMessageBoard = new MessageBoard();

        Thread reader = new Thread(new ThreadStart(myMessageBoard.Reader));
        reader.Name = "ReaderThread:";

        Thread writer = new Thread(new ThreadStart(myMessageBoard.Writer));
        writer.Name = "WriterThread:";

        reader.Start();
        writer.Start();
    }
}