A common scenario where avoiding deadlock is critical is a multi-threaded banking system that processes account transfers concurrently. During a transfer, a thread may need to lock both the source and destination accounts. If different threads acquire these locks in different orders, they can end up waiting indefinitely for each other, causing a deadlock and preventing transactions from completing.
Key Points: • Deadlocks occur when multiple threads hold resources while waiting for other resources locked by other threads. • A common prevention technique is to acquire locks in a consistent order, such as by account ID or resource ID. • Using lock timeouts, minimizing lock scope, and avoiding nested locks can further reduce deadlock risks.
Example: Imagine Thread A transferring money from Account 1 to Account 2 while Thread B transfers money from Account 2 to Account 1. If Thread A locks Account 1 and Thread B locks Account 2 simultaneously, both threads may wait forever for the other lock, causing a deadlock.
Code Example:
class Account {
private final int accountId;
public Account(int accountId) {
this.accountId = accountId;
}
public int getAccountId() {
return accountId;
}
}
public class TransferService {
public void transfer(Account from,
Account to) {
Account firstLock =
from.getAccountId() < to.getAccountId()? from
: to;
Account secondLock =
from.getAccountId() < to.getAccountId()? to
: from;
synchronized (firstLock) {
synchronized (secondLock) {
System.out.println(
"Transfer Completed");
}
}
}
}Interview Tip: A concise interview answer is: A banking fund-transfer system is a classic deadlock-prone scenario because transactions often require multiple account locks. I prevent deadlocks by enforcing a consistent lock acquisition order, minimizing lock duration, and using timeout-based locking when appropriate.