package com;
public class Account {
int debit(int money){
return 100 - money;
}
int credit(int money){
return 100 + money;
}
}
package com;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test {
public void transferMoney(Account from, Account to, int money){
synchronized (from){
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (to){
System.out.println(from.debit(money));
System.out.println(to.credit(money));
}
}
}
public static void main(String[] args) {
Account from = new Account();
Account to = new Account();
// new ThreadTest(from, to).run();
// System.out.println(123);
// new ThreadTest(to, from).run();
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.execute(new ThreadTest(from, to));
System.out.println("等待输出……");
executorService.execute(new ThreadTest(to, from));
executorService.shutdown();
}
}
package com;
public class ThreadTest implements Runnable{
private Account from;
private Account to;
public ThreadTest(Account from, Account to){
this.from = from;
this.to = to;
}
@Override
public void run() {
new Test().transferMoney(this.from, this.to, 10);
}
}
上面这种因为入参是同一个对象实例,所以因为入参顺序的不一致而导致了死锁,为了避免入参顺序不一致导致死锁,可以采用以下这种方式进行规避。
package com;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test {
public void transferMoney(Account from, Account to, int money){
int fromHash = System.identityHashCode(from);
int toHash = System.identityHashCode(to);
if(fromHash < toHash){
synchronized (from){
synchronized (to){
System.out.println(from.debit(money));
System.out.println(to.credit(money));
}
}
}else{
synchronized (to){
synchronized (from){
System.out.println(from.debit(money));
System.out.println(to.credit(money));
}
}
}
}
public static void main(String[] args) {
Account from = new Account();
Account to = new Account();
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.execute(new ThreadTest(from, to));
System.out.println("等待输出……");
executorService.execute(new ThreadTest(to, from));
executorService.shutdown();
}
}
改完后程序可以顺序执行,不再死锁。