My long-time java friend told me lock ordering and lock timeout are the 2 standard solutions, but here are additional suggestions directly or indirectly addressing deadlocks.
(“[top x]” means one of my favorite x techniques.)
For want of a better word, “stuck” is my general term meaning “no-progress” and includes
– lock grab,
– Object.wait(), waking up and grabbing lock
– socket accept(),
– long sleep(),
– endless loop,
– unbounded *recursion*
Now the solutions.
–to provide preemption
* [top 3] remain interruptible while getting “stuck”
** even if a recursion/loop calls no blocking method, the thread can still check for the interrupt status from time to time and exit if necessary. see http://download.oracle.com/javase/tutorial/essential/concurrency/interrupt.html
* tryInterruptibly(). Now, if thread 1 knows another thread is holding a mutex it can forcibly grab it, but how does it know which thread? –to break incremental acquisition
*[top 2] have a timeout while getting “stuck” — a wide-spread implementation
** example — in an endless loop, check how long we have been stuck and exit if necessary.
** example — lock timeout — A thread tries to acquire a lock in a specified period. Upon timeout, it release all it’s locks and go to wait status for a period. For example, release 1st chopstick if 2nd chopstick remains unavailable for x seconds. Achievable with tryLock()? Yes P279 [[ java concurrency in practice ]] I believe tryLock() can tell u the 2nd chopstick is unavailable and give you a chance to give up 1st chopstick held. See P69 [[pthreads]] and deadlock avoidance: release all locks voluntarily
* open call? impractical
–to break circular wait
* lockInterruptibly() of the Lock interface. It let’s u try to acquire a lock and remain responsive to interruption.
* reentrant/recursive lock. By default pthreads locks aren’t so a single thread can deadlock itself.
* [top 2] globally fixed resource acquisition order
* if you identify that 3 threads form a wait-for circle, then reverse one of the threads’ acquisition order
* finally() to release lock if using Lock objects. “synchronized” doesn’t need this.
* Release locks asap. minimize lock scope.
* [top 5] Make all methods finite. Avoid using locks while inside infinite loops or unbounded recursions.
–to break the need for mutex resources
* immutables. no need to lock anything to access them. CopyOnWrite is thread safe because it’s immutable.
* copy On Write
* copy the data for each thread, and sync up later
* replacing sync with atomic variables? both options can be criticized as risky