...
Code Block | ||
---|---|---|
| ||
class BankAccount implements Comparable {
private int balanceAmount; // Total amount in bank account
private final Object lock;
private BankAccount(int balance) {
this.balanceAmount = balance;
this.lock = new Object();
}
// Deposits the amount from this object instance to BankAccount instance argument ba
private void depositAllAmount(BankAccount ba) {
BankAccount former, latter;
if (compareTo(ba) < 0) {
former = this;
latter = ba;
} else {
former = ba;
latter = this;
}
synchronized (former) {
synchronized (latter) {
ba.balanceAmount += this.balanceAmount;
this.balanceAmount = 0; // withdraw all amount from this instance
ba.displayAllAmount(); // Display the new balanceAmount in ba (may cause deadlock)
}
}
}
private synchronized void displayAllAmount() {
System.out.println(balanceAmount);
}
public static void initiateTransfer(final BankAccount first, final BankAccount second) {
Thread t = new Thread(new Runnable() {
public void run() {
first.depositAllAmount(second);
}
});
t.start();
}
public int compareTo(BankAccount ba) {
if(this.balanceAmount < ba.balanceAmount) {
return -1;
} else if(this.balanceAmount > ba.balanceAmount) {
return 1;
} else {
return 0;
}
}
}
|
...
Code Block | ||
---|---|---|
| ||
class BankAccount { private int balanceAmount; // Total amount in bank account private final Lock lock = new ReentrantLock(); Lock getLock() { return lock; } private static final int TIME = 1000; // 1 second private BankAccount(int balance) { this.balanceAmount = balance; } // Deposits the amount from this object instance to BankAccount instance argument ba private void depositAllAmount(BankAccount ba) throws InterruptedException { while (true) { if (this.lock.tryLock()) { try { if (ba.lock.tryLock()) { try { ba.balanceAmount += this.balanceAmount; this.balanceAmount = 0; // withdraw all amount from this instance ba.displayAllAmount(); // Display the new balanceAmount in ba (may cause deadlock) break; } finally { ba.getLock()lock.unlock(); } } } finally { this.getLock()lock.unlock(); } } Thread.sleep(TIME); } } private void displayAllAmount() throws InterruptedException { while (true) { if (lock.tryLock()) { try { System.out.println(balanceAmount); break; } finally { lock.unlock(); } } Thread.sleep(TIME); } } public static void initiateTransfer(final BankAccount first, final BankAccount second) { Thread t = new Thread(new Runnable() { public void run() { try { first.depositAllAmount(second); } catch (InterruptedException e) { // Forward to handler } } }); t.start(); } } |
Deadlock is impossible in this code, becase because no routine method grabs a lock and holds it indefinitely. If a lock is acquired, but the system cannot proceed immediately, it releases the lock and sleeps before trying requesting the lock again.
Code that uses this lock behaves similar to synchronized code that uses the traditional monitor lock. ReentrantLock
provides several other capabilities, for instance, the tryLock() method does not block waiting if another thread is already holding the lock. The class java.util.concurrent.locks.ReentrantReadWriteLock
can be used when some thread requires a lock to write information while other threads require the lock to concurrently read the information.
...