这一章节我们来简单讨论一下死锁,其实死锁是一个比较大的话题,但是我这里只是根据我前面的银行转账的例子来说明,在后面会有详细的专栏来说明并发编程的各个方面的问题。
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(); } } }
总结:这一章节简单介绍了死锁。
这一章节就到这里,谢谢。
-----------------------------------
时间: 2024-11-02 23:30:20