Section 15.5. Thread Synchronization and Class Monitor


15.5. Thread Synchronization and Class Monitor

Often, multiple threads of execution manipulate shared data. If threads with access to shared data simply read that data, then any number of threads can access the data simultaneously without problems. However, when multiple threads share data and the data is modified by one or more of the threads, then indeterminate results may occur. If one thread is in the process of updating the data and another thread tries to update it too, the data will reflect only the later update. If the data is an array or other data structure in which the threads could update separate parts of the data concurrently, it is possible that part of the data will reflect the information from one thread while another part of the data will reflect information from another thread. When this happens, the program has difficulty determining when the data has been updated properly.

The problem can be solved by giving one thread at a time exclusive access to code that manipulates the shared data. During this time, other threads wishing to manipulate the data are kept waiting. When the thread with exclusive access to the data completes its data manipulations, one of the waiting threads is allowed to proceed. In this fashion, each thread accessing the shared data excludes all other threads from doing so simultaneously. This is called mutual exclusion or thread synchronization.

Visual Basic programmers use the .NET Framework's monitors to perform synchronization. Class Monitor provides the methods for locking objects to implement synchronized access to shared data. Locking an object means that only one thread can access that object at a time. When a thread wishes to acquire exclusive control over an object, the thread invokes the Monitor method Enter to acquire the lock on the data object. Each object has a SyncBlock that maintains the state of the object's lock. Methods of class Monitor use the data in an object's SyncBlock to determine the state of the lock for that object. After acquiring the lock for an object, a thread can manipulate that object's data. While the object is locked, all other threads attempting to acquire the lock on that object are blocked from acquiring the locksuch threads enter the Blocked state. When the thread that locked the shared object no longer requires the lock, that thread invokes Monitor method Exit to release the lock. This updates the SyncBlock of the shared object to indicate that the lock for the object is available again. At this point, if there is a thread that was previously blocked from acquiring the lock on the shared object, that thread acquires the lock to begin its processing of the object. If all threads with access to an object attempt to acquire the object's lock before manipulating the object, only one thread at a time will be allowed to manipulate the object. This helps ensure the integrity of the data.

Error-Prevention Tip 15.2

All code that modifies a shared object should first lock the object to ensure that only one thread at a time has access to the shared object.


Common Programming Error 15.1

Deadlock occurs when a waiting thread (let us call this thread1) cannot proceed because it is waiting (either directly or indirectly) for another thread (let us call this thread2) to proceed, while simultaneously thread2 cannot proceed because it is waiting (either directly or indirectly) for thread1 to proceed. Two threads are waiting for each other, so the actions that would enable either thread to continue execution never occur.


Visual Basic provides another means of manipulating an object's lockthe SyncLock statement. Wrapping a block of code in SyncLock...End SyncLock, as in

 SyncLock objectReference    ' code that requires synchronization goes here End SyncLock 


obtains the lock on the object to which the objectReference refers; thus, only one thread at a time can execute the code in a SyncLock statement. The objectReference is the same reference that normally would be passed to Monitor methods Enter, Exit, Pulse and PulseAll. When a SyncLock statement terminates for any reason, Visual Basic releases the lock on the object to which the objectReference refers. We explain SyncLock further in Section 15.8.

If a thread that owns the lock on an object determines that it cannot continue with its task until some condition is satisfied, the thread should call Monitor method Wait and pass as an argument the object on which the thread will wait until the thread can perform its task. Calling method Monitor.Wait from a thread releases the lock the thread has on the object that Wait receives as an argument and places that thread in the WaitSleepJoin state for that object. A thread in the WaitSleepJoin state of a specific object leaves that state when a separate thread invokes Monitor method Pulse or PulseAll with that object as an argument. Method Pulse transitions the object's first waiting thread from the WaitSleepJoin state to the Running state. Method PulseAll TRansitions all threads in the object's Wait-SleepJoin state to the Running state. The transition to the Running state enables the thread (or threads) to get ready to continue executing.

There is a difference between threads waiting to acquire an object's lock and threads waiting in an object's WaitSleepJoin state. Threads that call Monitor method Wait with an object as an argument are placed in that object's WaitSleepJoin state. Threads that are simply waiting to acquire the lock enter the conceptual Blocked state and wait until the object's lock becomes available. Then a Blocked thread can acquire the object's lock.

Monitor methods Enter, Exit, Wait, Pulse and PulseAll all take a reference to an objectusually the keyword Meas their argument.

Common Programming Error 15.2

A thread in the WaitSleepJoin state cannot re-enter the Running state to continue execution until a separate thread invokes Monitor method Pulse or PulseAll with the appropriate object as an argument. If this does not occur, the waiting thread will wait foreveressentially the equivalent of deadlock.


Error-Prevention Tip 15.3

When multiple threads manipulate a shared object using monitors, ensure that if one thread calls Monitor method Wait to enter the WaitSleepJoin state for the shared object, a separate thread eventually will call Monitor method Pulse to transition the thread waiting on the shared object back to the Running state. If multiple threads may be waiting for the shared object, a separate thread can call Monitor method PulseAll as a safeguard to ensure that all waiting threads have another opportunity to perform their tasks. If this is not done, indefinite postponement or deadlock could occur.


Performance Tip 15.2

Synchronization to achieve correctness in multithreaded programs can make programs run more slowly, as a result of monitor overhead and the frequent transitioning of threads between the Running, WaitSleepJoin and Running states. There is not much to say, however, for highly efficient but incorrect multithreaded programs!




Visual BasicR 2005 for Programmers. DeitelR Developer Series
Visual Basic 2005 for Programmers (2nd Edition)
ISBN: 013225140X
EAN: 2147483647
Year: 2004
Pages: 435

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net