Producer and Consumer with Synchronized Integer Buffer
' ************************************************************* ' * (C) Copyright 2003 by Deitel & Associates, Inc. * ' * and Prentice Hall. * ' * All Rights Reserved. * ' * * ' * DISCLAIMER: The authors and publisher of this book have * ' * used their best efforts in preparing the book. These * ' * efforts include the development, research, and testing of * ' * the theories and programs to determine their * ' * effectiveness. The authors and publisher make no warranty * ' * of any kind, expressed or implied, with regard to these * ' * programs or to the documentation contained in these books.* ' * The authors and publisher shall not be liable in any event* ' * for incidental or consequential damages in connection * ' * with, or arising out of, the furnishing, performance, or * ' * use of these programs. * ' ************************************************************* Imports System Imports System.Threading Public Class MainClass Shared Sub Main() ' create shared object used by threads Dim holdInteger As New SynchronizedIntegerBuffer() ' Random object used by each thread Dim randomObject As New Random() ' create Producer and Consumer objects Dim producer As New CProducer(holdInteger, randomObject) Dim consumer As New CConsumer(holdInteger, randomObject) ' create threads for producer and consumer ' set delegates for each thread Dim producerThread As New Thread(AddressOf producer.Produce) Dim consumerThread As New Thread(AddressOf consumer.Consume) ' name each thread producerThread.Name = "Producer" consumerThread.Name = "Consumer" ' start each thread producerThread.Start() consumerThread.Start() End Sub ' Main End Class ' Produces integers from 1 to 4 and places them in unsynchronized buffer. Public Class CProducer Private sharedLocation As SynchronizedIntegerBuffer Private randomSleepTime As Random Public Sub New(ByVal sharedObject As _ SynchronizedIntegerBuffer, ByVal randomObject As Random) sharedLocation = sharedObject randomSleepTime = randomObject End Sub Public Sub Produce() Dim count As Integer For count = 1 To 4 Thread.Sleep(randomSleepTime.Next(3000)) sharedLocation.Buffer = count Next Console.WriteLine(Thread.CurrentThread.Name & _ " done producing." & vbCrLf & "Terminating " & _ Thread.CurrentThread.Name & ".") End Sub End Class ' Consumes 4 integers from unsynchronized buffer. Public Class CConsumer Private sharedLocation As SynchronizedIntegerBuffer Private randomSleepTime As Random Public Sub New(ByVal sharedObject As _ SynchronizedIntegerBuffer, ByVal randomObject As Random) sharedLocation = sharedObject randomSleepTime = randomObject End Sub ' New Public Sub Consume() Dim count, sum As Integer For count = 1 To 4 Thread.Sleep(randomSleepTime.Next(3000)) sum += sharedLocation.Buffer Next Console.WriteLine(Thread.CurrentThread.Name & _ " read values totaling: " & sum & "." & vbCrLf & _ "Terminating " & Thread.CurrentThread.Name & ".") End Sub ' Consume End Class ' Synchronizes access to an Integer. Public Class SynchronizedIntegerBuffer Private mBuffer As Integer = -1 Private occupiedBufferCount As Integer Public Property Buffer() As Integer Get ' obtain lock on this object Monitor.Enter(Me) If occupiedBufferCount = 0 Then Console.WriteLine(Thread.CurrentThread.Name & _ " tries to read.") DisplayState("Buffer empty. " & _ Thread.CurrentThread.Name & " waits.") Monitor.Wait(Me) End If occupiedBufferCount -= 1 DisplayState(Thread.CurrentThread.Name & " reads " & _ mBuffer) Monitor.Pulse(Me) ' Get copy of buffer before releasing lock. ' It is possible that the producer could be ' assigned the processor immediately after the ' monitor is released and before the return ' statement executes. In this case, the producer ' would assign a new value to buffer before the ' return statement returns the value to the ' consumer. Thus, the consumer would receive the ' new value. Making a copy of buffer and ' returning the copy helps ensure that the ' consumer receives the proper value. Dim bufferCopy As Integer = mBuffer ' release lock on this object Monitor.Exit(Me) Return bufferCopy End Get Set(ByVal Value As Integer) ' acquire lock for this object Monitor.Enter(Me) ' if there are no empty locations, place invoking ' thread in WaitSleepJoin state If occupiedBufferCount = 1 Then Console.WriteLine(Thread.CurrentThread.Name & _ " tries to write.") DisplayState("Buffer full. " & _ Thread.CurrentThread.Name & " waits.") Monitor.Wait(Me) End If ' set new buffer value mBuffer = Value occupiedBufferCount += 1 DisplayState(Thread.CurrentThread.Name & " writes " & _ mBuffer) Monitor.Pulse(Me) Monitor.Exit(Me) End Set End Property Public Sub DisplayState(ByVal operation As String) Console.WriteLine("{0,-35}{1,-9}{2}" & vbCrLf, _ operation, mBuffer, occupiedBufferCount) End Sub End Class
1. | Thread Producer and Consumer | ||
2. | Producer and Consumer with Unsynchronized Integer Buffer |