Section 8.4. Synchronizing Threads


8.4. Synchronizing Threads

For all its advantages, introducing multithreading into your application opens up a Pandora's box of synchronization and concurrency-management issues. With multithreading, you have to worry about threads deadlocking themselves while contesting for the same resources, you must take steps to synchronize access to objects by concurrent multiple threads, and you need to be prepared to handle method reentrancy.

When it comes to programming components that are likely to be used by you or by others in multithreaded applications, you must ensure they are thread-safe. A thread-safe component is one that is equipped with mechanisms to prevent multiple threads from simultaneously accessing its methods and corrupting its state. Imagine, for example, a linked list component that provides methods for adding and removing elements from a list. When the component adds or removes an element, the component keeps the list in a temporarily inconsistent state, while node references are updated and written to reflect the change. If a client asks to add an element to the list on one thread (T1), and that thread is preempted by another thread (T2) during the request, T1 can leave the list in an inconsistent state, and T2 can crash trying to access the list. To make the list thread-safe, you should make sure that only one thread can access it at a time and that all other threads are barred until the current thread has finished.

With multithreaded applications, you must also concern yourself with avoiding deadlocks. In its simplest form, a deadlock occurs when one thread (T1), which owns thread-safe resource R1, tries to access another thread-safe resource (R2) at the same time that a second thread (T2), which owns R2, tries to access R1 (see Figure 8-2).

Figure 8-2. A deadlock between two threads


There are many ways to create a deadlock, and some of them are complex, involving multiple threads with multiple resources and synchronization objects. There are some defensive programming techniques to reduce the likelihood of deadlocks (such as always acquiring and releasing the resources in the same order), but by far the best prevention is to simply avoid them by design in the first place. You must analyze the intended behavior of your application's threads well before coding your first thread.


Multithreading defects are notoriously hard to isolate, reproduce, and eliminate. They often involve rare race conditions, and fixing one problem often introduces another. Traditionally, writing robust, high-performance multithreaded code was no trivial matter; it required a great deal of skill and discipline. .NET tries to ease multithreaded application development by providing a rich infrastructure compared to native Windows. In particular, .NET tries to simplify component concurrency management.

COM managed concurrency through the use of apartments, which were difficult to use and understand. .NET eliminates that awkward model.


By default, all .NET components execute in a multithreaded environment, and concurrent access to them by multiple threads is allowed. As a result, the state of the object can be corrupted if multiple threads access it at the same time. To avoid this problem, .NET provides two synchronization approaches: automatic and manual. Automatic synchronization allows you to simply decorate the component with an attribute and have .NET synchronize concurrent access to the object. Manual synchronization requires using .NET synchronization objects. In fact, .NET offers a range of options in the synchronization spectrum: you can synchronize access to a set of objects, an individual object, a particular method, or a critical code section, or you can just protect an individual class member. This range allows you to make trade-offs between ease of use and flexibility, and productivity and throughput.

The next two sections first describe .NET automatic synchronization for context-bound objects and then demonstrate the use of .NET locks provided for manual synchronization.



Programming. NET Components
Programming .NET Components, 2nd Edition
ISBN: 0596102070
EAN: 2147483647
Year: 2003
Pages: 145
Authors: Juval Lowy

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