Prevention
In this lesson, we discuss techniques to prevent different conditions that can cause a deadlock, from arising.
We'll cover the following
In the previous lesson, we saw four conditions that are needed for a deadlock to occur. Let’s now discuss the strategies to prevent each of these conditions.
Circular wait
Probably the most practical prevention technique (and certainly one that is frequently employed) is to write your locking code such that you never induce a circular wait. The most straightforward way to do that is to provide a total ordering on lock acquisition. For example, if there are only two locks in the system (L1
and L2
), you can prevent deadlock by always acquiring L1
before L2
. Such strict ordering ensures that no cyclical wait arises; hence, no deadlock.
Of course, in more complex systems, more than two locks will exist, and thus total lock ordering may be difficult to achieve (and perhaps is unnecessary anyhow). Thus, a partial ordering can be a useful way to structure lock acquisition so as to avoid deadlock. An excellent real-life example of partial lock ordering can be seen in i_mutex
before i_mmap_rwsem
” and more complex orders such as “i_mmap_rwsem
before private_lock
before swap_lock
before i_pages lock
”.
As you can imagine, both total and partial ordering require careful design of locking strategies and must be constructed with great care. Further, ordering is just a convention, and a sloppy programmer can easily ignore the locking protocol and potentially cause deadlock. Finally, lock ordering requires a deep understanding of the code base, and how various routines are called; just one mistake could result in the
Hold-and-wait
The hold-and-wait requirement for deadlock can be avoided by acquiring all locks at once, atomically. In practice, this could be achieved as follows:
Get hands-on with 1400+ tech skills courses.