A good real world example of deadlock is the use of printf in signal handlers in 213's tshlab. printf acquires a lock on stdout when it is called. Because of this, it is not asynch signal safe. If a signal handler begins running during a printf call in the main program, deadlock will occur. There are two resources, the stdout lock and control of the program. The main program has stdout and will not release it until it regains control. The signal handler has control and will not release it until it can run printf, which requires acquiring stdout. Thus there is a 2-cycle.
Note that this is different than thread safety. Printf is still thread safe because condition 4 does not apply in a multi-threaded scenario. While multiple threads can't be within printf concurrently, some thread will acquire it first, and has no dependencies on the others. So they will be able to line up and do their printfs in some sequence.
There are four ways to deal with deadlock. 1. Prevention 2. Avoidance 3. Recovery 4. Reboot. The main one of these is prevention which is to outlaw one of the four conditions stated above. With avoidance you dynamically examine requests to determine if the request places the system in a safe state. Recovery is to determine if deadlock has occurred and to free up one of the sources of the dead. Finally reboot is done usually with a watchdog timer which determines something is blocked in the system and reboots the system.