' *************************************************************
' * (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
|