Applying Patterns to Meet the Challenges of Concurrent Software

Douglas C. Schmidt
Department of Computer Science
Washington University

Invited contribution to the IEEE Concurrency Special Edition on Software Engineering for Parallel and Distributed Systems, Vol. 5, No. 3, Fall 1997.


1. Why Patterns are Important for Concurrent Software

It is expensive and error-prone to develop complex concurrent systems in domains like telecommunications, avionics, and distributed medical imaging. Past challenges centered largely on efficient use of expensive computer and network hardware resources (such as memory, disk, CPUs, and bandwidth). During the last decade, however, advances in VLSI technology and fiber optics have increased computer processing power by 2-3 orders of magnitude and network channel speeds by 5-6 orders of magnitude.

Unfortunately, software quality and programmer productivity have not increased as dramatically as hardware performance. Across the industry, this situation has yielded a ``concurrent software crisis,'' where hardware gets smaller, faster, cheaper, and more reliable, whereas concurrent software gets larger, slower, and more expensive to develop, debug, and maintain. Ironically, much of the effort associated with building concurrent software is spent rediscovering core synchronization concepts (such as active objects) and reinventing common components (such as futures, tasks, and monitors). The problem is that despite significant advances in concurrency algorithms, specification techniques, and low-level multi-threading APIs, most developers lack an intuition for how and when to best apply these techniques and APIs.

Patterns are an important means to alleviate the costly rediscovery and reinvention of proven concurrent software concepts and component solutions. Patterns are useful for documenting recurring micro-architectures, which are abstractions of common object-structures that expert developers apply to solve concurrent software problems (such as deadlock avoidance and wait-free synchronization). By studying and applying patterns, developers can often avoid traps and pitfalls that have traditionally been learned only by prolonged trial and error.

I believe that one of main issues involved in developing high quality parallel and distributed systems is identifying and documenting the key design patterns necessary to solve complex concurrent software problems. In order for concurrent software development to move from an art to an engineering discipline, successful practices and design expertise must be documented systematically and disseminated widely. Without a thorough understanding of successful concurrency patterns, developing complex concurrent systems will remain expensive and error-prone.

Until recently, patterns used to develop complex concurrent systems existed largely in programming folklore. Today, these concurrency patterns are becoming more thoroughly documented and more widely applied by researchers and developers. The remainder of this article explains the types of problems that patterns address and outlines our experiences applying patterns to reusable concurrent object-oriented communication frameworks.


2. How Patterns Address the Challenges of Concurrent Software

One source of concurrent software complexity is largely accidental, arising from limitations with existing development tools and platforms. For instance, the diversity of hardware and software platforms complicates the development of portable concurrent applications and tools that run on multiple OS platforms like POSIX, Win32, and embedded systems. These tool and platform limitations can be addressed by building concurrent object computing middleware (such as CORBA and DCOM) and object-oriented communication frameworks and components (such as ACE) that shield developers from tedious, error-prone, and non-portable programming details.

Core design patterns (like Adapter, Proxy, Facade, and Bridge [GoF]) have been widely used to motivate and document the strategic and tactical architectural designs of middleware, frameworks, and components. However, most of these design patterns were identified by developers of object-oriented user interfaces, which are judged primarily in terms of software quality factors like usability, extensibility, and portability. In contrast, concurrent software has traditionally emphasized high performance and correctness over other quality factors. Therefore, it has become increasingly important to document patterns that guide developers through the solution space for inherently difficult concurrent programming tasks such as the following:

Solving these inherent complexities requires much more than portable multi-threading APIs or Object Request Brokers -- it requires deep knowledge of successful patterns for developing concurrent protocols, components, frameworks, and system architectures. Much research remains to be done to identify, document, classify, and formalize these types of patterns and pattern languages.


3. Lessons Learned and Future Directions

My research group at Washington University has used design pattern-based reuse strategies for the past three years. These strategies are applied toward prototype and production communication systems we're building as part of the ACE project [Schmidt:94]. Thus far, our experience has been very positive. The following is a synopsis of our lessons learned thus far:

Over the next few years, I expect that a wealth of concurrent software design knowledge will be documented in pattern form and implemented in application frameworks. In addition, I believe that we'll see a closer connection between patterns and formalisms for specifying, analyzing, and validating concurrent software systems. However, these patterns will only be successful to the extent that researchers and developers read them, learn them, apply them, and write them. This article just scratches the surface of topics related to patterns for concurrent systems. To find out about books, online papers, electronic mailing lists, and conferences on concurrency patterns please see the Patterns Home Page (st-www.cs.uiuc.edu/users/patterns/patterns.html).


References

[GoF] E. Gamma, R. Helm, R. Johnson, and J. Vlissides, Design Patterns: Elements of Reusable Object-Oriented Software, Reading, MA: Addison-Wesley, 1995.

[McKenney] P. McKenney, Selecting Locking Primitives for Parallel Programs , CACM, (Special Issue on Software Patterns, D. Schmidt, Ralph Johnson, and M. Fayad Eds.), 39, 10, October 1996.

[Schmidt:94] D. Schmidt ``ACE: an Object-Oriented Framework for Developing Distributed Applications,'' Proceedings of the 6th USENIX C++ Technical Conference, Cambridge, MA, April, 1994.

[Schmidt:95] D. Schmidt, Using Design Patterns to Develop Reusable Object-Oriented Communication Software, CACM, (Special Issue on Object-Oriented Experiences, M. Fayad and W.T. Tsai Eds.), 38, 10, October 1995.