梓囚徒貧圭�鮗� ○ 賜 ★ 辛酔堀貧和鍬匈��梓囚徒貧議 Enter 囚辛指欺云慕朕村匈��梓囚徒貧圭�鮗� ● 辛指欺云匈競何��
!!!!隆堋響頼��紗秘慕禰厮宴和肝写偬堋響��
SyncLock elements
Do While ��elements。Count ゞ 3��
Thread。Sleep��1000��
Loop
items = elements。ToArray�┌�
End SyncLock
Dim item As Integer
For Each item In items
Console。WriteLine�─�Item �──�& item & ;��;��
Thread。Sleep��1000��
Next
End Sub
Sub Task2�┌�
Thread。Sleep��1500��
SyncLock elements
elements。Add��30��
End SyncLock
End Sub
Sub Main�┌�
elements。Add��10��
elements。Add��20��
Dim thread1 As New Thread��AddressOf Task1��
Dim thread2 As New Thread��AddressOf Task2��
thread1。Start�┌�
thread2。Start�┌�
End Sub
End Module
The iteration code waits until the collection count is 3。 However�察�this never happens�察�because
the thread that could make the collection count 3 is waiting for the lock to bee free。 The
bolded code is the waiting code that queries whether the collection count is 3。 If it is not�察�the
thread waits for 1 second and asks again。 But throughout all of this waiting�察�the lock is never given
up�察�and thus the second thread that could add an element is waiting。 The code will deadlock。
Without modifying the locks�察�here is a tweak that will avoid the deadlock ��the thread sleeps for
only 0。5 seconds instead of 1。5 seconds�察�so the writing thread can get in first before the reader
thread gets in���此�
Sub Task2�┌�
Thread。Sleep��500��
SyncLock elements
elements。Add��30��
End SyncLock
End Sub
´´´´´´´´´´´´´´´´´´´´´´Page 379´´´´´´´´´´´´´´´´´´´´´´´
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 357
The single change ��shown in bold�� makes the code work。 In the first version�察�the timing
of the code was such that the reading thread went first。 In this version�察�the writing thread goes
first。 This shows that deadlocks are often timing´related。
The annoying part of deadlocks is that your code¨s behavior is not deterministic。 Determin
istic behavior is when an action will result in a single result�察�as in the case with most source
code。 Typically�察�when you have a bug�察�you didn¨t think far enough ahead and can work through
the error systematically。 However�察�with threading�察�your code ceases to be deterministic�察�because
timing can change the behavior。 Timing can be an influence in many ways�此�resource swapping�察 �
debuggers�察�microprocessor speed�察�and a host of other features。
To make the code deterministic�察�you need to fix the part of the code that hung onto the lock
when it should not have。 Remember the cardinal rule�此�keep a lock for as short a time as possible。
You need to use a more advanced lock construct that allows you to wait for data to bee
available。 has quite a few constructs related to threading and synchronization�察�and each
construct is specific to the type of problem you are trying to solve。 In the case of a deadlock�察�you
want to use the Monitor type。 The Monitor type is an advanced synchronization type that allows
locking and pulsing of trigger signals for those threads that are waiting。
Let¨s return to our multiple cooks in the kitchen analogy。 Say one cook needs a particular
fish pan�察�which is already being used by another cook。 Does the waiting cook tap her foot beside
the cook doing the cooking�拭�Or does the waiting cook do something else and ask the cook using
the pan to inform her when the pan is free�拭�Most likely�察�the cook will do something else and
wait to be informed that the pan is free。
This concept of working together and being able to notify other lock users is a powerful
feature programmed into the Monitor type。 Monitor has the ability to take a lock�察�give it up so
others can get the lock�察�and then take it back again。
When using the Monitor type�察�you do not declare a block of code that is protected�察�because
Monitor is much more flexible than that。 For example�察�you could define a class that has an
instance´level lock mechanism�察�like this�此�
Class DoSomething
Public Sub GetLock�┌�
Monitor。Enter��Me��
End Sub
Public Sub ReleaseLock�┌�
Monitor。Exit��Me��
End Sub
End Class
Any code that uses a Monitor is not restricted to where it¨s placed in the code�察�but a Monitor
is bound to a thread。 So if a thread grabs a Monitor ��by calling the Enter�┌� method on the
Monitor object���察�it has control until the thread dies or the thread gives up control ��by calling the
Exit�┌� method on the Monitor object��。 This has the added benefit that�察�once having acquired a
lock�察�a Monitor can get it over and over again。 However�察�if the same thread locked the Monitor
five times�察�the same thread needs to release it five times before another thread can be granted
access to the lock。
The following is the rewritten two´thread source code that uses a Monitor。
´´´´´´´´´´´´´´´´´´´´´´Page 380´´´´´´´´´´´´´´´´´´´´´´´
358 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
Sub Task1�┌�
Dim items As Integer�┌�
Thread。Sleep��1000��
Monitor。Enter��elements��
Do While ��elements。Count ゞ 3��
Monitor。Wait��elements�察�1000��
Loop
items = elements。ToArray�┌�
Monitor。Exit��elements��
Dim item As Integer
For Each item In items
Console。WriteLine�─�Item �──�& item & ;��;��
Thread。Sleep��1000��
Next
End Sub
Sub Task2�┌�
Monitor。Enter��elements��
elements。Add��30��
Monitor。Pulse��elements��
Monitor。Exit��elements��
End Sub
The bolded code lines are the new pieces that use the Monitor type。 In the definition of the
first thread to get the lock�察�the Monitor。Enter�┌� method is called with the parameter elements�察 �
which�察�as in the earlier SyncLock example�察�defines the lock reference handle。 Once the lock has
been acquired�察�the thread checks to see if the list count is greater or equal to 3。 If the counter is
less than 3�察�the Monitor。Wait�┌� method is called。 The behavior of Monitor。Wait�┌� is similar to
Thread。Sleep�┌��察�except that the Monitor lock is given up。
Releasing the lock is a unique feature of a Monitor。 The lock is given up only during the
time that the caller is in Monitor。Wait�┌�。 When the Monitor。Wait�┌� method returns�察�the lock is
acquired again。 The code says that the thread is reawakened after 1 second。 After that second�察 �
the thread does not have the lock and needs to wait before it can acquire the lock。 If another
thread is holding onto the lock for a long time�察�it could take a while to get the lock back again。
Another way for the Monitor。Wait�┌� method to awaken is if a signal is sent by another
thread。 The code for the second thread uses Enter�┌� and Exit�┌��察�but also Pulse�┌�。 The Monitor。
Pul