Java Multithreading: Deadlock
The causes of deadlock and two things you can do about it.
This video also covers how to write a method that can safely acquire any number
of locks in any order without causing deadlock, using the tryLock() method of ReentrantLock.
Code For This Tutorial
The main program just runs
the firstThread() and secondThread()methods in different
threads. finish() is called after both threads finish.
The Runner class contains the
synchronization code.
import
java.util.Random;
import
java.util.concurrent.locks.Lock;
import
java.util.concurrent.locks.ReentrantLock;
class Runner {
private Account acc1 = new Account();
private Account acc2 = new Account();
private Lock lock1 = new
ReentrantLock();
private Lock lock2 = new
ReentrantLock();
private void
acquireLocks(Lock firstLock, Lock secondLock) throws
InterruptedException {
while(true) {
// Acquire locks
boolean gotFirstLock = false;
boolean gotSecondLock =
false;
try {
gotFirstLock =
firstLock.tryLock();
gotSecondLock =
secondLock.tryLock();
}
finally {
if(gotFirstLock
&& gotSecondLock) {
return;
}
if(gotFirstLock) {
firstLock.unlock();
}
if(gotSecondLock)
{
secondLock.unlock();
}
}
// Locks not acquired
Thread.sleep(1);
}
}
public void firstThread() throws
InterruptedException {
Random random = new Random();
for (int i = 0; i <
10000; i++) {
acquireLocks(lock1, lock2);
try {
Account.transfer(acc1, acc2,
random.nextInt(100));
} finally {
lock1.unlock();
lock2.unlock();
}
}
}
public void secondThread() throws
InterruptedException {
Random random = new Random();
for (int i = 0; i <
10000; i++) {
acquireLocks(lock2, lock1);
try {
Account.transfer(acc2, acc1,
random.nextInt(100));
} finally {
lock1.unlock();
lock2.unlock();
}
}
}
public void finished() {
System.out.println("Account
1 balance: " + acc1.getBalance());
System.out.println("Account
2 balance: " + acc2.getBalance());
System.out.println("Total
balance: "
+ (acc1.getBalance() + acc2.getBalance()));
}
}
Output:
Account 1 balance: 13175
Account 2 balance: 6825
Total balance: 20000
The main program (just creates and runs two threads):
public class App {
public static void main(String[]
args) throws Exception {
final Runner runner =
new Runner();
Thread t1 = new Thread(new Runnable() {
public void run() {
try {
runner.firstThread();
} catch
(InterruptedException e) {
// TODO
Auto-generated catch block
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
try {
runner.secondThread();
} catch
(InterruptedException e) {
// TODO
Auto-generated catch block
e.printStackTrace();
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
runner.finished();
}
}
And finally, the Account class implements a simple
bank account type thing.
class Account {
private int balance = 10000;
public void deposit(int amount) {
balance += amount;
}
public void withdraw(int amount) {
balance -= amount;
}
public int getBalance() {
return balance;
}
public static void
transfer(Account acc1, Account acc2, int amount) {
acc1.withdraw(amount);
acc2.deposit(amount);
}
}
Happy to found this blog. Good Post!. It was so good to read and useful to improve my knowledge as updated one, keep blogging. Hibernate Training in Electronic City
ReplyDeleteJava Training in Electronic City