梓囚徒貧圭�鮗� ○ 賜 ★ 辛酔堀貧和鍬匈��梓囚徒貧議 Enter 囚辛指欺云慕朕村匈��梓囚徒貧圭�鮗� ● 辛指欺云匈競何��
!!!!隆堋響頼��紗秘慕禰厮宴和肝写偬堋響��
Looking at the code within the block�察�you can see that the collection is accessed in two locations。
Using the exclusive SyncLock argument where a single thread can access only a single code
block�察�one thread will write to the collection�察�and another thread will read from the collection。
´´´´´´´´´´´´´´´´´´´´´´Page 375´´´´´´´´´´´´´´´´´´´´´´´
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 353
The SyncLock statement has a parameter that is a reference to lock against。 In both threads�察 �
the reference is elements。 The mon reference synchronizes access to code。 At any given
point in time�察�the code contained within the SyncLock block will have only a single thread
executing。 This implements the desired feature�察�where only one thread is accessing code that
reads or writes to the collection。 The flow of the program is as follows�此�
1。 Both threads wait。
2。 After a 1 second�察�thread 1 acquires a lock because no other thread has done so。
3。 Thread 1 executes its code。
4。 Once thread 1 has started executing the synchronized code�察�no other code can acquire
the lock that is associated with the variable elements。
5。 When thread 2 wakes up after a sleep of 1。5 seconds�察�it will attempt to acquire the lock�察 �
but it can¨t because thread 1 is still holding the lock。 So the second thread must wait。
6。 Thread 1 eventually exits the synchronized code block�察�allowing the second thread to
add an element to the collection。 This time�察�no exception is thrown。
The reference to lock against does not need to be the reference that is manipulated within
the code block。 The reference is just that�此�an arbitrary reference。 You could use a different
object instance�察�and even instantiate an object like this�此�
Dim _syncRoot As Object = New Object�┌�
。 。 。
SyncLock _syncRoot
。 。 。
End SyncLock
When using exclusive blocks�察�you need to use them when reading or writing the object。
Don¨t think that you need an exclusive lock only when modifying the data�察�because a reader
might be reading a state that is being modified。 As the example of the collection demonstrated�察 �
modifying a collection while it is being read causes an inconsistency and an exception。 The
following code does not have a lock for the reading of the collection�察�and it results in an excep
tion being thrown。
。 。 。
Module ThreadProblem
Dim elements As List��Of Integer�� = New List��Of Integer���┌�
Sub Task1�┌�
Thread。Sleep��1000��
Dim item As Integer
For Each item In elements
Console。WriteLine�─�Item �──�& item & ;��;��
Thread。Sleep��1000��
Next
End Sub
´´´´´´´´´´´´´´´´´´´´´´Page 376´´´´´´´´´´´´´´´´´´´´´´´
354 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 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
Getting back to the code that worked�察�it would seem that all is OK。 From a code´execution
perspective�察�that¨s true。 But from an execution´efficiency perspective�察�everything is not OK�察 �
because the reading of the collection is causing the writer to wait unnecessarily。
Again�察�this collection example illustrates the difficulty with writing multithreaded code。
You want to be able to add elements to a collection without needing to wait for other threads to
iterate a collection。 You want to be efficient�察�as well as being logically correct。
Synchronizing with Cloning
One way of making a lock more efficient is to clone the object so that the local copy that you
read from does not lock and hinder another thread。 The two´thread example could be rewritten
as follows�此�
。 。 。
Module ThreadProblem
Dim elements As List��Of Integer�� = New List��Of Integer���┌�
Sub Task1�┌�
Dim items As Integer�┌�
Thread。Sleep��1000��
SyncLock elements
items = elements。ToArray�┌�
End SyncLock
Dim item As Integer
For Each item In items
Console。WriteLine�─�Item �──�& item & ;��;��
Thread。Sleep��&H3E8��
Next
End Sub
´´´´´´´´´´´´´´´´´´´´´´Page 377´´´´´´´´´´´´´´´´´´´´´´´
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 355
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 code still uses a lock�察�but only in the places where it is necessary。 When the collection
is being iterated�察�the lock is applied to the operation of copying the collection to an array
��ToArray�┌���。 For the array iteration itself�察�there is no lock。 When writing to the collection�察�there
is a lock。
So�察�how can it be more efficient to take a snapshot of the collection�察�since taking a snap
shot takes time�拭�The answer is that normally it is not more efficient�察�but it is more time´slice
effective。
Consider a word processor that loads some text。 When Microsoft Word loads text�察�it imme
diately displays the first page�察�allowing you to edit right away。 In the background�察�you see the
other pages being loaded and prepared for editing。 Using the snapshot approach�察�you get the
same effect。
As a general threading rule�察�use locks as sparingly as possible�察�but use them whenever
necessary。 If you do use them�察�use them for as little code as possible。 Locks synchronize access
to resources�察�and thus only a single thread can be executing for a locked piece of code。 The less
time code is locked�察�the faster your code will be。
How Not to Deadlock Your Code ��Mostly��
A deadlock makes code stop executing。 A deadlock occurs when one piece of code has a lock
and waits for some information to bee available。 However�察�the information does not
bee available�察�because another thread that could provide that information is waiting for a
lock to bee free。
I¨ve said that if you are using locked code�察�you should use it as sparingly as possible。 That¨s
because using locks can lead to deadlocks。 Deadlocks are a royal pain in the butt。
Consider the following two´thread collection example。
。 。 。
Module ThreadProblem
Dim elements As List��Of Integer�� = New List��Of Integer���┌�
´´´´´´´´´´´´´´´´´´´´´´Page 378´´´´´´´´´´´´´´´´´´´´´´´
356 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��
SyncLock elements
Do While ��elements。Count ゞ 3��
Thread。Sl