It's difficult to find real life examples because normally you wouldn't design your software to use tryLock()
. The example given in the javadoc is as follows:
Lock lock = ...;
if (lock.tryLock()) {
try {
// manipulate protected state
} finally {
lock.unlock();
}
} else {
// perform alternative actions
}
But you wouldn't design your software like that, would you? What if the lock is never (or almost never) available, how will that affect your program? What if it's always available? You have a method that does one of two things depending on pure chance. That's not good design, it increases randomness and complexity.
Okay, so it's not something you decide to use because it's elegant. What is it good for?
Imagine you've inherited a legacy project designed by an insane programmer and it has severe issues with deadlocks. It has synchronized
methods peppered all around and needs to be booted at least once every week because it locks up. First you convert all the synchronized
methods to use Lock
instead. Now you no longer block forever on synchronized
, but can use tryLock(long, TimeUnit) to timeout and prevent deadlocks.
Now you've solved the reboot causing deadlocks, but it's still not optimal since you're spending time waiting. With additional refactoring you manage to reduce the locks, but unfortunately you can't do proper lock ordering just yet. Your end code looks like this, where inner locks are acquired with tryLock()
or outerlock is released to prevent deadlock:
Lock outerLock = ...;
outerLock.lock(); // Here we block freely
try {
Lock innerLock = ...;
if (innerLock.tryLock()) { // Here we risk deadlock, we'd rather "fail-fast"
try {
doSomethingProtectedByLocks();
} finally {
innerLock.unlock();
}
} else {
throw new OperationFailedException(); // Signal the calling code to retry
}
} finally {
outerLock.unlock();
}
I think the problem is mainly with wording. The Javadoc talks about "actions" (like unlocking an outer lock) being performed based on whether the lock was acquired or not, but it's easy to read it as if the thread would have 2 separate responsibilities determined by the lock state.