这一章节我们来简单讨论一下死锁,其实死锁是一个比较大的话题,但是我这里只是根据我前面的银行转账的例子来说明,在后面会有详细的专栏来说明并发编程的各个方面的问题。
1.什么是死锁?
是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。
2.怎样会引起死锁?
(1) 互斥条件:一个资源每次只能被一个进程使用;
(2) 请求与保持条件:既拿着现有资源,又去申请其他资源,但申请不上一直被阻塞;
(3) 不剥夺条件:不能够通过优先级来剥夺资源使用权的资源;
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
3.我们前面的例子是怎样引起死锁的?
(1)死锁产生的过程:
账号1原有200元
账号2原有300元
线程1:从账户1转300元到账户2
线程2:从账户2转400元到账户1
(2)引起死锁的代码块:
public void transfer(int fromAccount, int toAccount, double money) {
if (accounts[fromAccount] < money) {
System.out.println(Thread.currentThread().getName() + "出现死锁");
return;
}
accounts[fromAccount] -= money;
System.out.printf("从" + fromAccount + "账户转出%10.2f元,", money);
accounts[toAccount] += money;
System.out.printf("从" + toAccount + "账户转入%10.2f元,", money);
System.out.printf("总数:%10.2f元", getTotal());
System.out.println();
}
(3)原因:
当转账的钱大于现有的余额,将会产生死锁
(4)解决方案:
但是由于现实业务不允许这种情况出现,因此我们直接return就解决了死锁的问题。
(5)如果是其他多线程竞争资源,里面不是像上面一样的return,而且等待,就会出现死锁的情况。
4.完整例子:
package com.ray.ch17;
public class Bank {
private final double[] accounts;
public double[] getAccounts() {
return accounts;
}
public Bank(int n, double initBalance) {
accounts = new double[n];
for (int i = 0; i < accounts.length; i++) {
accounts[i] = initBalance;
}
}
public double getTotal() {
double total = 0;
for (int i = 0; i < accounts.length; i++) {
total += accounts[i];
}
return total;
}
public void transfer(int fromAccount, int toAccount, double money) {
if (accounts[fromAccount] < money) {
System.out.println(Thread.currentThread().getName() + "出现死锁");
// Thread.currentThread().wait();//如果是其他的多线程,可能在这里是wait,从而出现真正的死锁
return;
}
accounts[fromAccount] -= money;
System.out.printf("从" + fromAccount + "账户转出%10.2f元,", money);
accounts[toAccount] += money;
System.out.printf("从" + toAccount + "账户转入%10.2f元,", money);
System.out.printf("总数:%10.2f元", getTotal());
System.out.println();
}
public int size() {
return accounts.length;
}
}
package com.ray.ch17;
import java.util.Random;
public class TransferThread implements Runnable {
private Bank bank;
private final double MAX;
public TransferThread(Bank bank, double max) {
this.bank = bank;
this.MAX = max;
}
@Override
public void run() {
while (true) {
double amount = MAX * Math.random();
int countOfAccount = bank.getAccounts().length;
bank.transfer(new Random().nextInt(countOfAccount),
new Random().nextInt(countOfAccount), amount);
}
}
}
package com.ray.ch17;
public class Test {
public static void main(String[] args) {
Bank bank = new Bank(100, 10000);
for (int i = 0; i < 2; i++) {
TransferThread transferThread = new TransferThread(bank, 10000);
Thread thread = new Thread(transferThread);
thread.start();
}
}
}
总结:这一章节简单介绍了死锁。
这一章节就到这里,谢谢。
-----------------------------------