A **sequential algorithm** is the formal description of the behavior of an *abstract* state machine. A **program** is a sequential algorithm written in a programming language. A **process** is a program executed on a *concrete* machine, characterized by its *state* (values of the registers). If the process follows one single control flow (i.e. one program counter) then it is a **sequential process**, or thread. A set of sequential state machines that run simultaneously and interact through shared memory through a *shared medium* is called **concurrency**. In a concurrent system there must be something shared. ##### Advantages of concurrent systems: - efficiency: run in parallel different stuff - simplification of the logic by dividing the task in simpler tasks, running them in different processes and combining the results together. ### Features of a concurrent system We can assume many features: - Reliable vs Unreliable - Synchronous vs Asynchronous - Shared memory vs Channel-based communication **Reliable** system: every process correctly executes its program **Asynchronous:** no timing assumption (every process has its own clock, which are independent one from the other) **Shared medium:** A way is through a shared memory area, another way is through message passing. For this part of the course we assume that every process has a local memory but can access a shared part of the memory. We will assume that memory is split into registers (will see later). For now, we will assume that processes won't fail. We also assume that we have one processor per process. But actually the processor can be a shared resource (more processes than processors).