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)