Consistent Lock Ordering

Consistent lock ordering prevents a common form of deadlock by requiring every thread to acquire multiple locks according to the same global order. If all participating threads follow that order, a circular wait cannot form.

A deadlock can occur when two threads hold different locks and each waits for the lock held by the other. For example, thread A holds `lock1` and waits for `lock2`, while thread B holds `lock2` and waits for `lock1`.

Consistent lock ordering assigns an ordering to locks, such as `lock1` before `lock2`. Every thread that needs both locks must acquire `lock1` first and `lock2` second. A thread needing only one lock simply acquires that lock.

The important property is that the ordering is global for the locks that can be acquired together. It is not enough for each method to use a consistent order independently if different methods disagree about which lock comes first.

This technique prevents the circular-wait condition of deadlock. It does not by itself eliminate other concurrency problems, such as starvation or poor performance caused by excessive lock contention.

Key points

Interview questions

How does consistent lock ordering prevent deadlocks?

It gives locks a shared ordering, such as `lockA` before `lockB`. Every thread must acquire `lockA` before attempting `lockB`. Therefore, a thread cannot hold `lockB` while waiting for `lockA`, which removes the circular-wait pattern needed for this type of deadlock.

Suppose one thread locks A then B, while another locks B then A. What can happen?

The threads can deadlock if each acquires its first lock before the other acquires its second lock. The first thread holds A and waits for B, while the second holds B and waits for A. The problem is the inconsistent acquisition order, so both paths should follow the same hierarchy.

How would you choose a lock ordering for two Java objects?

I would define a deterministic ordering that every relevant code path can apply. For objects with stable unique identifiers, I could order by those identifiers; for known resources, an explicit hierarchy can be clearer. The key is that the ordering must be deterministic and shared by every operation that can acquire both locks.

Does consistent lock ordering guarantee that a Java program has no deadlocks?

No. It prevents deadlocks caused by cycles involving locks covered by the ordering discipline, but a program can still deadlock through other synchronization mechanisms or code paths that violate the discipline. For example, mixing monitors with other blocking resources can introduce dependencies outside the lock hierarchy. The guarantee therefore depends on applying the ordering consistently to the relevant resource graph.