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();
}
}
测试结果: