梓囚徒貧圭�鮗� ○ 賜 ★ 辛酔堀貧和鍬匈��梓囚徒貧議 Enter 囚辛指欺云慕朕村匈��梓囚徒貧圭�鮗� ● 辛指欺云匈競何��
!!!!隆堋響頼��紗秘慕禰厮宴和肝写偬堋響��
probably not consistent�察�and that is why you need to synchronize access to state。
Let¨s consider a simple collection class example。 The following source code executes
in the calling thread�察�instantiates a list collection�察�and then adds two numbers to the collection。
Dim elements As List��Of Integer��= New List��Of Integer���┌�
elements。Add��10��
elements。Add��20��
In the next step�察�we define a method that iterates the elements collection ��which is declared at
a higher scope��。
Sub Task1�┌�
Thread。Sleep��1000��
Dim item As Integer
For Each item In elements
Console。WriteLine�─�Item �──�& item & ;��;��
Thread。Sleep��1000��
Next
End Sub
This thread iterates the data�察�and the two Thread。Sleep�┌� calls put the threads to sleep for
1000 milliseconds�察�or 1 second。 By putting the thread to sleep�察�we can artificially construct a
situation where another thread adds to the collection while the collection is being iterated。
The method that adds an element to the collection is defined as follows�此�
Sub Task2�┌�
Thread。Sleep��1500��
elements。Add��30��
End Sub
´´´´´´´´´´´´´´´´´´´´´´Page 372´´´´´´´´´´´´´´´´´´´´´´´
350 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
The Task1�┌� and Task2�┌� methods are started in separate threads as follows�今此�
elements。Add��10��
elements。Add��20��
Dim thread1 As New Thread��AddressOf Task1��
Dim thread2 As New Thread��AddressOf Task2��
thread1。Start�┌�
thread2。Start�┌�
Running the threaded code will generate an exception�察�but not immediately。 First�察�the caller
thread creates and starts thread1 and thread2。 thread1 goes to sleep for 1 second�察�and thread2
goes to sleep for 1。5 seconds。 After thread1 awakens�察�one item in the collection is iterated�察�and
thread1 goes to sleep for another second。 But before thread1 reawakens�察�thread2 awakens and
adds an element to the collection。 When thread1 reawakens and attempts to iterate another
element in the collection�察�an exception is generated�察�as shown in Figure 13´4。
Figure 13´4。 Exception thrown after adding element to the collection�察�as shown in the Visual Basic IDE
The InvalidOperationException is thrown to indicate that you can¨t add elements to a
collection while iterating a collection。 The collection classes think it is a bad idea to modify and
iterate a collection at the same time。 I agree with the collection classes�察�because doing so could
give unpredictable results。
The problem in the source code is how to use the collection classes in a multithreaded
context。 In the example�察�items are added to the collection while the collection is being iterated。
A monly suggested approach is to use the type System。Collections。ObjectModel。
ReadOnlyCollection�察�as in the following example。
Imports System。Collections。ObjectModel
Imports System。Threading
´´´´´´´´´´´´´´´´´´´´´´Page 373´´´´´´´´´´´´´´´´´´´´´´´
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 351
Module ThreadProblem
Dim elements As List��Of Integer�� = New List��Of Integer���┌�
Sub Task1�┌�
Thread。Sleep��1000��
Dim item As Integer
Dim listElements As New ReadOnlyCollection��Of Integer����elements��
For Each item In listElements
Console。WriteLine�─�Item �──�& item & ;��;��
Thread。Sleep��1000��
Next
End Sub
Sub Task2�┌�
Thread。Sleep��1500��
elements。Add��30��
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 change is the bolded code�察�which instantiates the type System。Collections。
ReadOnlyCollection�察�to which we pass the elements list。 The ReadOnlyCollection provides the
base class for a generic read´only collection。 The For Each iterator then iterates a collection
that is read´only�察�but based on the original collection。 However�察�running the code will result in
the same exception。 This demonstrates that ReadOnlyCollection does not take a snapshot�察�but
masks the collection。 The mask disables the addition of items to the collection�察�but because the
other thread is taking a shortcut and editing the original collection�察�the read´only collection is
modified as well。
Let¨s say that converting the collection into a read´only collection had worked。 It would
not have solved anything。 A read´only collection means that the second thread would generate
an exception because you can¨t add elements to a collection that is read´only。 The point is that
when writing multithreaded code that shares variables�察�you don¨t have an easy solution�察�because
you are trying to solve the problem of how to keep multiple cooks productive in a single kitchen。
We are trying to solve a classic reader/writer problem�察�where some threads are interested
only in reading the data�察�and other threads are interested only in modifying the data。 One way
to synchronize the readers and writers is to use an exclusive lock�察�so that only one thread may
read or write。
´´´´´´´´´´´´´´´´´´´´´´Page 374´´´´´´´´´´´´´´´´´´´´´´´
352 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
Using Exclusive Locks
When using exclusive locks in �察�you are saying�察 �Only one thread may execute this piece
of code。 ̄ If two threads want to execute a particular piece of code�察�one will be granted access�察 �
while the other thread waits until the granted thread has exited the code block。 It is important
to understand that an exclusive lock grants access to code�察�not data�察�but that code could access
data。 And because only one thread is accessing the code�察�it is implied that only one thread can
access the data。
The following is an example of code that uses exclusive locks。
。 。 。
Module ThreadProblem
Dim elements As List��Of Integer�� = New List��Of Integer���┌�
Sub Task1�┌�
Thread。Sleep��1000��
SyncLock elements
Dim item As Integer
For Each item In elements
Console。WriteLine�─�Item �──�& item & ;��;��
Thread。Sleep��1000��
Next
End SyncLock
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 bolded lines use the SyncLock and End SyncLock keywords�察�which represent a code block of
exclusive access。 The thread is granted access to only a single code block in each instance。
Looking at the code within the block�察�you can see that the collection is accessed in two locations。
Using the exclusi