Mega Code Archive

 
Categories / VB.Net / Thread
 

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