  This book is about the theoretical foundations of concurrency. For us, a _distributed system_ is a collection of sequential computing entities, called _processes_ , that cooperate to solve a problem, called a _task_. The processes may communicate by message passing, shared memory, or any other mechanism. Each process runs a program that defines how and when it communicates with other processes. Collectively these programs define a _distributed algorithm_ or _protocol_. It is a challenge to design efficient distributed algorithms in the presence of failures, unpredictable communication, and unpredictable scheduling delays. Understanding when a distributed algorithm exists to solve a task, and why, or how efficient such an algorithm can be