11 Avoiding deadlocks

 

This chapter covers

  • Identifying deadlocks
  • Avoiding deadlocks
  • Deadlocking with channels

A deadlock, in a concurrent program, occurs when executions block indefinitely, waiting for each other to release resources. Deadlocks are an undesirable side effect of certain concurrent programs where concurrent executions are trying to acquire exclusive access to multiple resources at the same time. In this chapter, we will analyze the conditions under which deadlocks might occur and offer strategies to prevent them. We’ll also discuss certain deadlocking conditions that can occur when using Go channels.

Deadlocks can be quite tricky to identify and debug. As with race conditions, we can have a program that runs without hitches for a long time, and then suddenly the execution halts, for no obvious reason. Understanding the reasons why deadlocks happen allows us to make programming decisions to avoid them.

11.1 Identifying deadlocks

What is the simplest concurrent program we can write that creates all the conditions for a deadlock to occur? We can create a simple program with just two goroutines competing for two exclusive resources, as shown in figure 11.1. The two goroutines, called red() and blue(), each try to hold two mutex locks at the same time. Since the locks are exclusive, the only time one goroutine can acquire both locks is when the other goroutine is not holding any of them.

Figure 11.1 Two goroutines competing for two exclusive resources

11.1.1 Picturing deadlocks with resource allocation graphs

11.1.2 Deadlocking in a ledger

11.2 Dealing with deadlocks

Summary