您好,欢迎访问一九零五行业门户网

【JAVA并发编程实战】锁顺序死锁

package cn.study.concurrency.ch10; public class account { private string staffaccount; //账号 private string password; //密码 private int balance; //账户余额 public account(int money) { this.balance = money; } public string getstaffaccount() { return staffaccount; } public void setstaffaccount(string staffaccount) { this.staffaccount = staffaccount; } public string getpassword() { return password; } public void setpassword(string password) { this.password = password; } public void debit(int amount) { system.out.println("转出账户:" + amount); } public void credit(int amount) { system.out.println("转入账户:" + amount); } public int getbalance() { return balance; } public void setbalance(int balance) { this.balance = balance; } }
package cn.study.concurrency.ch10; import java.util.concurrent.executorservice; import java.util.concurrent.executors; import javax.naming.insufficientresourcesexception; /** * 通过制定确定的锁顺序来避免死锁 * @author xiaof * */ public class deathlock { public void transfermoney(account fromaccount, account toaccount, int amount) throws insufficientresourcesexception { synchronized(fromaccount) { synchronized(toaccount) { //按参数的顺序上锁,这个依据参数的调用方法的顺序 if(fromaccount.getbalance() < amount) { //账户余额不足,无法转账 throw new insufficientresourcesexception(); } else { fromaccount.debit(amount); toaccount.credit(amount); } } } } /** * 这个用来在无法判定枷锁顺序的时候的加时赛锁 */ private static final object tielock = new object(); public static void transfermoney2(final account fromaccount, final account toaccount, final int amount) throws insufficientresourcesexception { /** * 辅助内部类 * @author xiaof * */ class helper { public void transfer() throws insufficientresourcesexception { //内部类可以随意访问外部类成员 //按参数的顺序上锁,这个依据参数的调用方法的顺序 if(fromaccount.getbalance() < amount) { //账户余额不足,无法转账 throw new insufficientresourcesexception(); } else { fromaccount.debit(amount); toaccount.credit(amount); } } } //返回给定对象的哈希码,该代码与默认的方法 hashcode() 返回的代码一样,无论给定对象的类是否重写 hashcode() int fromhash = system.identityhashcode(fromaccount); int tohash = system.identityhashcode(toaccount); //根据hash值判定加锁顺序,那么一样的对象的锁顺序就一定一样 if(fromhash < tohash) { synchronized(fromaccount) { synchronized(toaccount) { new helper().transfer(); } } } else if(tohash < fromhash) { synchronized(toaccount) { synchronized(fromaccount) { new helper().transfer(); } } } else { //如果很不巧,hash值是一样的,那么就需要一个加时赛的机制,先获取外部锁,然后再此基础上对两个对象随机上锁 synchronized(tielock) { synchronized(fromaccount) { synchronized(toaccount) { new helper().transfer(); } } } } } static account account1 = new account(999); static account account2 = new account(999); public static void main(string[] args) throws insufficientresourcesexception { //对于第一个方法很容易死锁 //比如:当有两个同时执行这个方法的调用时候 // deathlock dl = new deathlock(); //这个时候第一个调用在锁了account1,然后第二个调用锁了account2 //同时第一个需要account2,第二个需要account1,这就发生竞争死锁了 // dl.transfermoney(account1, account2, 998); // dl.transfermoney(account2, account1, 998); // // dl.transfermoney2(account1, account2, 998); executorservice pool = executors.newfixedthreadpool(10); for(int i = 0; i < 5; ++ i) { pool.execute(new runnable() { @override public void run() { try { deathlock.transfermoney2(account1, account2, 998); } catch (insufficientresourcesexception e) { e.printstacktrace(); } } }); } for(int i = 0; i < 5; ++ i) { pool.execute(new runnable() { @override public void run() { try { deathlock.transfermoney2(account2, account1, 998); } catch (insufficientresourcesexception e) { e.printstacktrace(); } } }); } pool.shutdown(); } }
测试结果:
其它类似信息

推荐信息