“The Analytical Engine has no pretensions whatever to originate anything. It can do whatever we know how to order it to perform.”
Concurrency is hard. When your program is performing dozens of tasks at the same time, a single crash in any of them can cause all of them to stop. Perhaps one of the tasks was supposed to wait for some critical calculation to complete, but it proceeded too early. Perhaps one task corrupted a pointer that another was using, leading to a mysterious segmentation fault. Perhaps two tasks overwrote each other’s intermediate calculations, leading to incorrect final results. Once you begin writing software that goes beyond a single coherent algorithm, you quickly learn that you are entering a world with a completely new set of programming errors that you never imagined. Each line of code can interact and interfere with other parts of the system in new, unintended, and unpredictable ways. In other words, concurrency is hard. This book aims to make it less so.
Chapter Objectives
In this chapter, we will address the following instructional objectives:
Our focus in this book is to establish a foundation of key principles and techniques that are be used to implement concurrent systems software. This class of software ranges from operating systems (OS) and web servers to databases and scientific modeling platforms. What these types of programs have in common is that they subdivide complicated tasks into smaller ones that can be run at the same time. In doing so, these approaches introduce nondeterminism and complexity, as the programmer must give up some control over what steps and calculations will be performed in which particular order. If the programmer writes code that says tasks A, B, and C can be executed in any order, they will quickly learn whether or not that claim is actually true.
At this point, some readers may object: they do not plan to write systems software, so this material is not relevant for them. While the first part of that claim may be true (or it may not), the latter is certainly not the case. The principles used to build systems and infrastructure can be applied to more traditional applications; if your application uses event handlers to detect mouse clicks or key presses, you have a concurrent program. If your code is structured to use a web-based application programming interface (API), you have a concurrent program. If your application performs graphical calculations or applies artificial intelligence, you have a concurrent program (or you should, as it would run faster).
In short, concurrency is everywhere. Mastering the concepts and principles of concurrent programming can help you build better software, whether the end result is a new application or a platform for applications. In this chapter, we will introduce the major themes and guiding principles that we will use throughout the book. We will also define some key terminology and notation that are helpful in characterizing concurrent systems. Without further delay, let us begin our exploration.