VB.Net/Thread/Producer Consumer
Producer and Consumer with Synchronized Integer Buffer
<source lang="vbnet"> " ************************************************************* " * (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
</source>
Producer and Consumer with Unsynchronized Integer Buffer
<source lang="vbnet"> Imports System Imports System.Threading Public Class MainClass
Shared Sub Main() " create shared object used by threads Dim holdInteger As New UnsynchronizedIntegerBuffer() " 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 UnsynchronizedIntegerBuffer Private randomSleepTime As Random Public Sub New(ByVal sharedObject As _ UnsynchronizedIntegerBuffer, 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 UnsynchronizedIntegerBuffer Private randomSleepTime As Random Public Sub New(ByVal sharedObject As _ UnsynchronizedIntegerBuffer, 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 " Definition of a shared integer without synchronization mechanisms. Public Class UnsynchronizedIntegerBuffer
Private mBuffer As Integer = -1 Property Buffer() As Integer Get Console.WriteLine(Thread.CurrentThread.Name & _ " reads " & mBuffer) Return mBuffer End Get Set(ByVal Value As Integer) Console.WriteLine(Thread.CurrentThread.Name & _ " writes " & Value) mBuffer = Value End Set End Property " Buffer
End Class
</source>
Thread Producer and Consumer
<source lang="vbnet"> Imports System.Threading Module Module1
Public Buffer As Integer Public BufferEmpty As Boolean = True Public MonitorLock As Object = New Object() Sub Producer() Dim Value As Integer = 0 Do Monitor.Enter(MonitorLock) If (BufferEmpty) Then BufferEmpty = False Buffer = Value If (Value = 0) Then Value = 1 Else Value = 0 End If Console.WriteLine("Producer: " & Buffer) End If Monitor.Exit(MonitorLock) Loop While (True) End Sub Sub Consumer() Dim Value As Integer Do Monitor.Enter(MonitorLock) If (Not BufferEmpty) Then BufferEmpty = True Thread.CurrentThread.Sleep(1000) Value = Buffer Console.WriteLine("Consumer: " & Value) End If Monitor.Exit(MonitorLock) Loop While (True) End Sub Sub Main() Dim ProducerThread As Thread Dim ConsumerThread As Thread ProducerThread = New Thread(AddressOf Producer) ConsumerThread = New Thread(AddressOf Consumer) ProducerThread.Start() ConsumerThread.Start() End Sub
End Module
</source>