This algorithm checks if the given owner is part of a deadlock. by traversing all paths of the lock/owner
depedency graph as described above. The graph is directed, so it is
clear in which direction we are traversing it. Please note that no
physical graph is constructed, but is implicite in the code and the
stack structure.
1 : protected boolean wouldDeadlock(Object ownerId, Set path) {
2 : path.add(ownerId);
3 : Set locks = (Set) globalOwners.get(ownerId);
4 : for (Iterator i = locks.iterator(); i.hasNext();) {
5 : GenericLock mylock = (GenericLock) i.next();
6 : Collection conflicts = mylock.getConflictingWaiters(ownerId);
7 : for (Iterator j = conflicts.iterator(); j.hasNext();) {
8 : Object waitingOwnerId = j.next();
9 : if (path.contains(waitingOwnerId)) {
10: return true;
11: } else if (wouldDeadlock(waitingOwnerId, path)) {
12: return true;
13: }
14: }
15: }
16: path.remove(ownerId);
17: return false;
18: }
In lines 3-5 it inspects all locks it (partially) holds and finds the
owners that are currently waiting for given owner. As explained above
lines 6-8 GenericLock#getConflictingWaiters does not traverse all owners waiting for the lock, but only those that are
waiting for the part of the lock acquired by the given owner. Those
owners will need investigation if the current owner - or anyone else
waiting for it - is also waiting for them. If so we have a deadlock.
Both to guarantee termination and actually find out if there is such a
cycle indicating a deadlock in the graph lines 2 and 16 we
remember the owners of all paths we traverse. As the sequence is not
important we store them in a set for fast access. In lines
9-10 we check if the owner already is in our path and if so we
have been here before which means there is a cycle in the graph and we
thus have a deadlock. If not, in lines 11-12 we recursively repeat the check for each owner that
waits for us. As the graph is directed and finite this algorithm
either terminates with false in line 17 or there is a cycle
in it which will be detected as explained above and will lead to a
termination with true. You can see that in both cases the algorithm terminates.