1. 死锁是什么?
2. 死锁产生的条件
- 互斥访问: 只有一个线程在某一个时间可以访问共享资源;否则进程不能阻止其他进程访问共享资源,资源如果是sharable--可共享访问的,将带来访问状态的问题。
- 拥有等待条件:一个进程当前必须拥有至少一个资源,并请求由其他进程所拥有的额外的资源。
- 非抢占条件:一个线程所占有的资源只有在该线程自愿释放的情况下才能释放。
- 循环等待:每个线程等待的资源被另一个线程所持有,而另一个线程反过来等待前一个线程释放资源。
3. 死锁demo
package com.fqyuan.thought;
import java.util.Random;
import java.util.concurrent.locks.ReentrantLock;
/*
* 1. Initialization is important, very important!
* 2. Design functions which take fields as its parameters is useful !
*/
public class DeadLock {
public static void main(String[] args) {
Process process = new Process();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
process.opr1();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
process.opr2();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
}
process.finished();
}
}
class Account {
private int balance = 10000;
public void withdraw(int count) {
balance -= count;
}
public void depoist(int count) {
balance += count;
}
public int getBalance() {
return balance;
}
public static void transfer(Account account1, Account account2, int count) {
account1.withdraw(count);
account2.depoist(count);
}
}
class Process {
private Account account1;
private Account account2;
private ReentrantLock lock1;
private ReentrantLock lock2;
private Random random;
public Process() {
account1 = new Account();
account2 = new Account();
lock1 = new ReentrantLock();
lock2 = new ReentrantLock();
random = new Random();
}
// Break the condition: hold and wait, if not holding both, release the one
// kept.
private void acquireLocks(ReentrantLock lock1, ReentrantLock lock2) throws InterruptedException {
boolean lock1Status = false;
boolean lock2Status = false;
while (true) {
try {
lock1Status = lock1.tryLock();
lock2Status = lock2.tryLock();
} finally {
if (lock1Status && lock2Status)
return;
else if (lock1Status)
lock1.unlock();
else if (lock2Status)
lock2.unlock();
}
Thread.sleep(5);
}
}
// Break the condition: circular waiting, if acquire lock with the same
// order. Here i mean, in opr1() acquireLock(lock1, lock2), while in opr2()
// acquireLock(lock2,lock1).
// Just acquire the lock in the same sequence to avoid circular waiting!
public void opr1() throws InterruptedException {
for (int i = 0; i < 1E5; i++) {
try {
acquireLocks(lock1, lock2);
Account.transfer(account1, account2, random.nextInt(5));
} finally {
lock1.unlock();
lock2.unlock();
}
}
}
public void opr2() throws InterruptedException {
for (int i = 0; i < 1E5; i++) {
try {
acquireLocks(lock2, lock1);
Account.transfer(account2, account1, random.nextInt(5));
} finally {
lock1.unlock();
lock2.unlock();
}
}
}
public void finished() {
System.out.println("Account 1 balance: " + account1.getBalance());
System.out.println("Account 2 balance: " + account2.getBalance());
System.out.println("Total balance: " + (account1.getBalance() + account2.getBalance()));
}
}
运行结果:After transferring, account1 remained: 3995
After transferring, account2 remained: 16005
After transferring, account1 && account2 totally have: 20000