Multithreaded programming is complicated. I hope that the previous chapter has sufficiently demonstrated how hard it is to coordinate multiple threads that work on shared data. There are just so many possibilities for writing code that doesn't always work correctly or to implement a fix that slows a program down so much that the new and improved parallel solution is actually slower than the original single-threaded code.
In this chapter, I will continue exploring design patterns (with a bit of architectural thinking thrown in) in a completely different direction. Instead of working on shared data, the patterns from this chapter will be used to write parallel tasks that are independent of each other. To achieve that, they use multiple copies of data and communicate with messages.
Introducing such patterns, however, often requires...