| 本帖最后由 朱晓杰 于 2013-5-9 18:47 编辑 
 今天在整理死锁的时候,自己写了一个小例子,死锁的现象倒是出现了 ,可是在开发过程中要如何才能避免程序死锁呢?据我所知要定义锁的顺序,并在整个程序中都按照这个顺序来获取锁,请问该如何制定锁的顺序呢?下面是我的死锁的例子。
 
 银行转账死锁示例
 分析发生死锁的原因 :所有的线程并不是按照相同的顺序来获取锁,锁的顺序取决于传递的参数顺序,而这些参数顺序又取决于外部输入,如果线程a和线程b同时转账,线程a从张三向李四转账,线程b从李四向张三转账,那么就会发生 死锁:复制代码/*
* 需求:简单的银行转账,它将资金从一个账户转到另一个账户
* 在开始转账之前,需要获得两个Account的锁,以确保以原子的方式更新账户中的余额,且不能破坏不可变的条件,如账户的余额不能为负数
* 
*/
/*账户类*/
class Account{
        private String accountName;//账号
        private int balance;//资金总额
        public Account(String accountName,int balance){
                this.accountName = accountName;
                this.balance = balance;
        }
        /**/
        public String getAccountName() {//获取账号
                return accountName;
        }
        public int getBalance() {//获取账号余额
                return balance;
        }
        
        public void debit(int amount){//更新转出方余额 
                this.balance -= amount;
        }
        
        public void credbit(int amount){//更新转入方余额
                this.balance += amount;
        }
}
class TransferAccount implements Runnable{
        public Account fromAccount;//转出账户
        public Account toAccount;//转入账户
        public int amount;//转出金额
        public TransferAccount(Account fromAccount,Account toAccount,int amount){
                this.fromAccount = fromAccount;
                this.toAccount = toAccount;
                this.amount = amount;
        }
        public void run(){
                while(true){
                        synchronized(fromAccount){
                                synchronized(toAccount){
                                        if(fromAccount.getBalance() <= 0){//转账进行的条件:判断转出账户的余额是否大于0
                                                System.out.println(fromAccount.getAccountName() + "账户余额不足,无法进行转账");
                                                return;
                                        }else{
                                                fromAccount.debit(amount);//更新转出账户的余额:-
                                                toAccount.credbit(amount);//更新转入账户的余额:+
                                        }
                                }
                        }
                        System.out.println(fromAccount.getAccountName() + "......" + fromAccount.getBalance());//打印转出账户的余额
                        System.out.println(toAccount.getAccountName() + "---" + toAccount.getBalance());//打印转入账户的余额
                }
        }
}
public class BankTransfer {
        public static void main(String[] args) {
                Account fromAccount = new Account("张三",100000);
                Account toAccount = new Account("李四",200000);
                
                Thread a = new Thread(new TransferAccount(fromAccount,toAccount,1));
                Thread b = new Thread(new TransferAccount(toAccount,fromAccount,2));
                
                a.start();
                b.start();
        }
}
a:new TransferAccount(fromAccount,toAccount,1)
 b:new TransferAccount(toAccount,fromAccount,2)
 如果执行顺序不恰当,那么a可能获得fromAccount的锁并且等待toAccount的锁,然而此时b拥有toAccount的锁,并正在等待fromAccount的锁。
 |