30.07.2013 Views

Visual Basic.NET How to Program (PDF)

Visual Basic.NET How to Program (PDF)

Visual Basic.NET How to Program (PDF)

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Chapter 14 Multithreading 617<br />

The Get and Set accessors are implemented similarly. As in Fig. 14.7, the consumer<br />

thread (Fig. 14.11)performs the tasks specified in the consumer object’s Consume<br />

method. The consumer thread gets the value of the CHoldIntegerSynchronized<br />

object’s Buffer property (Fig. 14.11, line 26) by invoking the Get accessor at Fig. 14.9,<br />

lines 16–61. In Fig. 14.9, line 19 invokes Moni<strong>to</strong>r method Enter <strong>to</strong> acquire the lock on<br />

the CHoldIntegerSynchronized object.<br />

The If structure in lines 23–31 determines whether occupiedBufferCount is<br />

0. If this condition is True, lines 24–25 output a message indicating that the consumer<br />

thread tried <strong>to</strong> read a value, and lines 27–28 invoke method DisplayState <strong>to</strong> output<br />

another message indicating that the buffer is empty and that the consumer thread waits.<br />

Line 30 invokes Moni<strong>to</strong>r method Wait <strong>to</strong> place the calling thread (i.e., the consumer)<br />

in the WaitSleepJoin state for the CHoldIntegerSynchronized object and releases<br />

the lock on the object. Now, another thread can invoke an accessor method of the<br />

CHoldIntegerSynchronized object’s Buffer property.<br />

The consumer thread object remains in the WaitSleepJoin state until the thread is<br />

notified that it can proceed—at which point the thread returns <strong>to</strong> the Started state and<br />

waits for the system <strong>to</strong> assign a processor <strong>to</strong> the thread. When the thread reenters the Running<br />

state, the thread implicitly reacquires the lock on the CHoldIntegerSynchronized<br />

object, and the Get accessor continues executing with the next statement after<br />

Wait. Line 35 decrements occupiedBufferCount <strong>to</strong> indicate that the shared buffer<br />

now is empty (i.e., a consumer cannot read the value, but a producer can place another<br />

value in<strong>to</strong> the shared buffer). Lines 37–38 output a line <strong>to</strong> the command window specifying<br />

the value that the consumer is reading, and line 42 invokes Moni<strong>to</strong>r method<br />

Pulse with the CHoldIntegerSynchronized object as an argument. If there are<br />

any waiting threads in that object’s SyncBlock, the first waiting thread enters the Started<br />

state, indicating that the thread can attempt its task again as soon as the thread is assigned<br />

a processor. The Pulse method returns immediately. Line 55 creates a copy of<br />

mBuffer before releasing lock. It is possible that the producer could be assigned the<br />

processor immediately after the lock is released (line 58) and before the Return statement<br />

executes (line 60). In this case, the producer would assign a new value <strong>to</strong> mBuffer<br />

before the Return statement returns the value <strong>to</strong> the consumer. Thus, the consumer<br />

would receive the new value. By, making a copy of mBuffer and returning the copy,<br />

we ensure that the consumer receives the proper value. Line 58 invokes Moni<strong>to</strong>r<br />

method Exit <strong>to</strong> release the lock on the CHoldIntegerSynchronized object, and<br />

the Get accessor returns bufferCopy <strong>to</strong> its caller.<br />

Study the outputs depicted in Fig. 14.12. Observe that every Integer produced is<br />

consumed exactly once—no values are lost, and no values are consumed more than once.<br />

This occurs because the producer and consumer cannot perform tasks unless it is "their<br />

turn." The producer must go first; the consumer must wait if the producer has not produced<br />

a value since the consumer last consumed; and the producer must wait if the consumer<br />

has not yet consumed the value that the producer most recently produced. Execute<br />

this program several times <strong>to</strong> confirm that every Integer produced is consumed<br />

exactly once.<br />

In the first and second sample outputs, notice the lines indicating when the producer<br />

and consumer must wait <strong>to</strong> perform their respective tasks. In the third sample output,<br />

notice that the producer and consumer were able <strong>to</strong> perform their tasks without waiting.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!