梓囚徒貧圭�鮗� ○ 賜 ★ 辛酔堀貧和鍬匈��梓囚徒貧議 Enter 囚辛指欺云慕朕村匈��梓囚徒貧圭�鮗� ● 辛指欺云匈競何��
!!!!隆堋響頼��紗秘慕禰厮宴和肝写偬堋響��
if the lock has not been acquired�察�then return from the method call。 If you do use a timeout�察�before
you attempt to manipulate shared code�察�you need to reference the property IsReaderLockHeld or
IsWriterLockHeld to ensure that you have acquired the lock。 In the reader threads�察�after having
acquired the reader locks�察�the items are iterated。
*Note The example seems to break the rule regarding keeping locks for as short a time possible�察�since it
holds onto the lock while iterating。 In the case of a reader/writer implementation�察�you have a unique situation
in that you should be manipulating data that is mostly to be read�察�which implies that most of the time�察�you will
be treating the shared data as read´only。 For those times when you are writing to the shared data�察�it is fine if the
thread must wait a moment or two。 A reader/writer lock does not make sense if you do not have data that is essen
tially read´only。 In other situations�察�you should use the Monitor approach�察�as described in the previous section。
The example demonstrates handling data that is mostly to be read�察�since it has three threads
reading and one thread writing。 It is important to make sure that you don¨t end up writing while
holding a read´only lock。
´´´´´´´´´´´´´´´´´´´´´´Page 384´´´´´´´´´´´´´´´´´´´´´´´
362 CH AP T E R 1 3 * L E A R N I N G A B OU T M U L T I TH R E A DI N G
Running the code results in the following output。
Thread 1 waiting for read lock
Thread 1 has read lock
Thread 1 Item ��10��
Thread 2 waiting for read lock
Thread 2 has read lock
Thread 2 Item ��10��
Thread 4 waiting for write lock
Thread 3 waiting for read lock
Thread 1 Item ��20��
Thread 2 Item ��20��
Thread 1 releasing read lock
Thread 2 releasing read lock
Thread 4 has write Lock
Thread 4 releasing write lock
Thread 3 has read lock
Thread 3 Item ��10��
Thread 3 Item ��20��
Thread 3 Item ��30��
Thread 3 releasing read lock
In the generated output�察�the sequence of events is as follows�此�
1。 Thread 1 wants and acquires a read´only lock。
2。 Thread 1 outputs the first number in the collection。 Thread 1 then sleeps�察�which lets in
another thread for execution。
3。 Thread 2 wants and acquires another read´only lock。
4。 Thread 2 outputs the first number in the collection。 Thread 2 then sleeps�察�which lets in
another thread for execution。
5。 Thread 4 wants a writer lock and is kept on hold。
6。 Thread 3 wants a read´only lock�察�but because thread 4 has asked for a writer lock and is
queued�察�thread 3 is put on hold。 At this step�察�threads 3 and 4 are put on hold and are
waiting for the read´only locks of threads 1 and 2 to be released。
7。 Threads 1 and 2 output the remaining numbers in the collection。
8。 Threads 1 and 2 release the read´only locks。
9。 Thread 4 is given a writer lock�察�and thread 3 is still on hold。
10。 Thread 4 writes to the collection and releases the writer lock。
11。 Thread 3 acquires a read´only lock and iterates the individual numbers�察�including the
number added by thread 4。
´´´´´´´´´´´´´´´´´´´´´´Page 385´´´´´´´´´´´´´´´´´´´´´´´
C HA P TE R 1 3 * L E AR N IN G AB O U T M U L T IT HR E AD IN G 363
Notice that the reader/writer lock makes the sequence of reading and writing events orderly�察 �
so that the shared state is always consistent。 The reader/writer lock does not hinder or stop
deadlocks�察�which can occur if you are not careful with how you write your code。 The reader/
writer lock is concerned about only the code that is used to manage data。
Implementing a Producer/Consumer Architecture
The producer/consumer technique has never been defined as a type�察�but it is used throughout
many multithreaded applications。 The idea behind a producer/consumer architecture is to
split the problem into two parts。 One side is the producer of data�察�information�察�and tasks。 The
producer wraps up the information into a task to be executed。 The other side is the consumer�察 �
and it is responsible for unwrapping the information and doing something with it。
Using a Hidden Producer/Consumer Implementation
In Windows GUIs�察�multithreaded applications are not allowed to access UI ponents if they
are not the thread that created the UI element。 To get around that problem�察�the Windows。Forms
library uses the Invoke�┌� method。 To demonstrate�察�we¨ll create a GUI application that uses another
thread to periodically increment a counter that is displayed in a text box。
Follow these steps�此 �
1。 Create a new Windows Forms application�察�and set it as the startup project if it isn¨t already
��right´click its name and select Set as StartUp Project��。
2。 Drag a TextBox control onto Form1 in the design window。
3。 Select the TextBox control。 If the Properties window isn¨t visible�察�right´click the control
and select Properties。
4。 Change the TextBox¨s Name property to txtMessage。
5。 Right´click the form and select View Code。
6。 Add the following code。
Imports System。Threading
Public Class Form1
Private _counter As Integer
Private Sub IncrementCounter�┌�
Me。txtMessage。Text = ;Counter �──�& _counter & ;��;
_counter ��= 1
End Sub
Delegate Sub DelegateIncrementCounter�┌�
´´´´´´´´´´´´´´´´´´´´´´Page 386´´´´´´´´´´´´´´´´´´´´´´´
364 CH AP T E R 1 3 * L E A R N I N G A B OU T M U L T I TH R E A DI N G
Private Sub PeriodicIncrement�┌�
Do While True
Invoke��New DelegateIncrementCounter��AddressOf IncrementCounter����
' You can't call the GUI using a thread other than the GUI thread
'IncrementCounter�┌�
Thread。Sleep��1000��
Loop
End Sub
Private _thread As Thread
End Class
7。 Switch back to the design view and double´click the form�察�which should take you back
to the code view in the Form1_Load�┌� method。
8。 Add the following code to the Form1_Load�┌� method。
Private Sub Form1_Load��ByVal sender As System。Object�察�_
ByVal e As System。EventArgs�� Handles MyBase。Load
_thread = New Thread��AddressOf PeriodicIncrement��
_thread。Start�┌�
End Sub
When Form1 is loaded�察�the Form1_Load�┌� method is executed�察�which instantiates a new
thread�察�which then executes the PeriodicIncrement�┌� method。 Within the implementation of
PeriodicIncrement�┌� is a never´ending loop�察�which calls the Form。Invoke�┌� method�察�to which
we pass a delegate。 The delegate is the method IncrementCounter�┌��察�which increments a
counter and outputs the result to the text box txtMessage。
From a user perspective�察�it would seem obvious to call the method IncrementCounter�┌�
directly from the other thread ��_thread��。 How