It most certainly does have to do with avoiding a dead-lock situation.
Option 1 could result in dead-lock, due to unlucky timing. If thread 1 would call getLocks(A, B), and thread 2 would call getLocks(B, A) then thread 1 (while running) could obtain the lock on A and be moved to runnable state by the thread schedular. Thread 2 could then be moved to running state by the thread schedular and obtain the lock on B. From here on out it no longer matters which thread continues to run, because thread 1 owns the lock on A and thread 2 owns the lock on B. Both threads are blocked because they both need the lock held by the other thread. Enter the horror that is dead-lock. Which also disqualifies option 4.
Option 2 could not result in dead-lock, because even if the thread schedular performs some nasty scheduling logic, which ever thread executed getLocks(A, B) first, will own the lock on A and block the other thread from ever obtaining the lock on B. Dead-lock avoided. Disqualifies option 3 and option 5, because this is the single valid option we were looking for. Option 3 could not be guarenteed anyway, due to the unpredicability of thread schedular magic, as the getLocks() method itself is not synchronized using the intrinsic lock of the object it is called on. [ March 21, 2008: Message edited by: Jelle Klap ]
Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.