【JAVA並發程式實戰】鎖順序死鎖

高洛峰
發布: 2016-11-17 13:39:15
原創
1766 人瀏覽過

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(); } }
登入後複製

檢驗結果:

【JAVA並發程式實戰】鎖順序死鎖

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!