CS 134

Deadlock and Deadlock Detection

Let's talk about deadlock and how to detect it. We'll have a simulation to help us understand the concepts. We have two processes, “Alice” and “Bob”, and two resources, “Pan” and “Whisk”. In our example, we have a familiar analogy to the real world, but our resources could be anything that gets grabbed by a process and then released, and while one process has a resource, other processes that want it have to wait.

  • Dog speaking

    So like locks in OS/161?

  • PinkRobot speaking

    Exactly!

Simulator and Visualization

Deadlock Status:

Exercise 1: Requesting Resources

In the simulator above, do the following (reset the simulation before you start if you've been playing around with it):

  • Use the dropdown boxes to give both the Pan and the Whisk to Alice (or give them both to Bob if you prefer) by setting them to “Allocated”.
    • In the graph display, you'll see that the Pan and Whisk resources now have a solid green edge pointing from them to the process they were allocated to.
  • Now, set the dropdown boxes for the other process to “Request” one of the resources already held by the first process.
    • In the graph display, you'll see a new dashed purple edge from the process to the resource.
    • If the process can't get the resource, it will be blocked, which means the process will be put to sleep while it's waiting for the resource. The simulator greys out all the dropdown boxes for the resource while it sleeps.
  • If you make the first process release the resource the second resource requested, the second process will wake up and acquire the resource.
    • The graph and table will update to show the new state where the second process has the resource.

Exercise 2: More Things

  • Pig speaking

    I always want MORE!

  • PinkRobot speaking

    You can click the following buttons to add some more processes and resources to the simulation.

  • BlueRobot speaking

    That said, you can see most deadlock phenomena with just two processes and two resources.

  • PinkRobot speaking

    If you want to go back to just two processes and two resources, you can refresh the page.

Exercise 3: Creating Deadlock

Try to create a series of allocations and requests such that every process ends up stuck waiting. When you succeed, you'll see the status change to “Deadlock Detected”.

Looking at the graph, what do you see that indicates deadlock?

  • Cat speaking

    There's clearly a cycle in the graph. That's a deadlock, right?

  • PinkRobot speaking

    Right, deadlock is a circular wait. Each process is waiting for a resource that's held by another process in the cycle.

  • Dog speaking

    I'm sad. Now that it's deadlocked, it doesn't work anymore because everything is stuck. I guess I should reload the page to reset it.

  • PinkRobot speaking

    Actually, don't do that. We can try to fix the situation without starting from scratch!

Conditions for Deadlock

We've already seen one condition for deadlock, circular wait. But for deadlock to be a problem, we need four conditions to be met:

  1. Mutual Exclusion: Resources must be held in a mutually exclusive way. That is, only one process can use a resource at a time.
  2. Hold and Wait: Processes must hold resources while waiting for others.
  3. No Preemption: Resources cannot be forcibly taken from a process.
  4. Circular Wait: There must be a circular wait chain of processes.

Here are two checkboxes to allow us to turn off the second and third conditions. If the simulator above is in a deadlocked state, changing these conditions will allow us to break the deadlock.

Checking or unchecking these options will scroll the page back to the simulation so you can see their effect.
    • If you turn off hold and wait, you can make a process give up on waiting for a resource (by switching to “Uninterested”) which will release the resource and the deadlock will disappear.
    • If you turn on resource preemption, you can take a resource away from a process that's asleep (by switching it to “Uninterested”) which will allow another process to get the resource and continue, so the deadlock will disappear.
  • Cat speaking

    So, if we don't have all four conditions, we can't have deadlock?

  • PinkRobot speaking

    Exactly.

Deadlock Prevention

We can prevent deadlock by attacking any of the four conditions.

Eliminate Mutual Exclusion

Suppose several processes want to print pages to the printer. One approach is to give processes exclusive access to the printer. But perhaps they don't really need an interactive conversation with the printer; maybe they just need something to receive the print job and then the printer can print that job when it's ready. With this approach, any process can create print jobs at any time, and the printer can print them in whatever order it wants.

Coming up with designs that don't require mutual exclusion is one way to prevent deadlock.

  • Goat speaking

    Meh. So just get rid of all the locks and hope for the best! Everyone for themselves!

  • PinkRobot speaking

    No, that's not what we're saying. We're saying that sometimes you can design things so that you don't need locks.

Eliminate Hold and Wait

Normally, when we try to acquire a lock, our process sleeps until it can get the lock. But if we can't get the lock, we're stuck. Rather than wait indefinitely, we could instead have processes give up on waiting after some time has passed.

  • Rabbit speaking

    POSIX provides pthread_mutex_timedlock for this purpose. If you can't get the lock in a certain amount of time, you can give up.

  • Duck speaking

    So just put that in a loop and keep trying?

  • PinkRobot speaking

    No. That would be no better than just sleeping. If we had a circular wait, we'd still be stuck. It wouldn't technically be deadlock, but it's the same issue. We call that livelock.

  • BlueRobot speaking

    Instead we have to do something different, such as releasing all the resources we have and then trying to request all the things we need from scratch.

Eliminate No Preemption

Preempting resources is rarely a good idea. If a process is in the middle of writing to a file, we don't want to take the file away from it. But if we're stuck in a deadlock situation, killing one of the processes (and thus releasing its resources) is one way to break the deadlock.

  • Duck speaking

    So we just kill a process and hope for the best?

  • PinkRobot speaking

    That's one way to do it. But it's a bit like using a sledgehammer to crack a nut. It's a bit heavy-handed.

Eliminate Circular Wait

If we can prevent a circular wait, we can prevent deadlock. One way would be to assign an order to resources and require processes to request resources in that order.

  • Dog speaking

    So we just have to make sure that everyone requests resources in the same order?

  • PinkRobot speaking

    That's the goal, but it's trickier than you might think. Sometimes when you thought you only needed one resource, you later find you need another one. In those cases, the order you're supposed to request resources in may not be the same as the order you actually find that you need them.

Deadlock Detection

  • Duck speaking

    So how do we detect deadlock?

We can use a graph to represent the resources and processes and the requests and allocations between them. If we find a cycle in the graph, we have a deadlock.

Unfortunately, the graph algorithm for detecting cycles has time complexity \(\mathrm{O}(V + E)\), where \(V\) is the number of vertices and \(E\) is the number of edges. That's not terrible, but we probably don't want to run it all the time.

  • Rabbit speaking

    Unix-like systems tend not to bother with deadlock detection. They just hope for the best.

  • Hedgehog speaking

    That's not very reassuring.

  • Goat speaking

    Meh. If you have a deadlock, you'll know about it because everything will be stuck.

(When logged in, completion status appears here.)