A situation in which several entities (e.g. processes) wait in a circular fashion for each other. Each entity waits for a resource held by another entity which will never be freed because that entity again waits for a resource held by yet another entity until the loop is closed. Instead for waiting on resources the entities could also wait for actions of another entity. You can imagine it as 4 cars reaching at the same time an intersection with a "give way to right"-rule.

More technically there are four preconditions for a deadlock to occur:

  1. Mutual Exclusion: Each resource can only be used by one entity. (More generally: by a fixed number of entities. If a resource can be used by e.g. three entities at the same time, it can still be modeled with mutual exclusion by splitting it up into three resources .)

  2. Wait and Hold: Entities which wait for a resource hold on to the resources they have already allocated.

  3. No preemption: None of the allocated resources can be withdrawn from an entity by another.

  4. Circular wait: The waiting graph forms a circle.

There are three things one can do against deadlocks: First, design your system so that at least one of the above preconditions does not hold. This is called deadlock prevention. If no deadlock prevention is there but the resource allocation algorithm uses a strategy to hand out resources that always keeps the system in a deadlock-safe state, it is called deadlock avoidance. The algorithm every computer scientist has to learn is Dijkstra's Banker's Algorithm. If neither of the two is there but the system is monitoring its entities and e.g. kills one of those in a deadlock circle, it is called deadlock detection (and resolution). Each of these solutions becomes more difficult in a distributed system.