尊敬的各位论坛的小伙伴们,对于下列代码不能解释清楚死锁的原因:
首先贴代码吧:
Account.java
public class Account {
private String acccountNo;
private double balance;
private volatile boolean flag = false;
private int i = 0; public Account() { } public Account(String accountNo, double balance) {
this.acccountNo = acccountNo;
this.balance = balance;
} public String getAcccountNo() {
return acccountNo;
} public void setAcccountNo(String acccountNo) {
this.acccountNo = acccountNo;
} public double getBalance() {
return this.balance;
} public void draw(double drawAmount) {
synchronized (Account.class) {
if (!flag) {
try {
Account.class.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
System.out.println(Thread.currentThread().getName() + "取钱:" + drawAmount);
balance -= drawAmount;
System.out.println("账户余额为:" + balance);
// 将标识账户是否有存款的旗标设为false
if (balance < 0) {
i++;
System.out.println(
"******************************************************************************************************************************************"
+ i);
flag = false;
Account.class.notifyAll();
}
}
System.out.println(flag);
} } public void deposit(double depositAmount) {
synchronized (Account.class) {
if (flag) {
try {
Account.class.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
System.out.println(Thread.currentThread().getName() + "存款:" + depositAmount);
balance += depositAmount;
System.out.println("账户余额为:" + balance);
if (balance > 0) {
flag = true;
Account.class.notifyAll();
}
}
System.out.println(flag);
}
}
}
DepositThread.java
public class DepositThread extends Thread {
// 模拟用户账户
private Account account;
private double depositAmount; public DepositThread(String name, Account account, double depositAmount) {
super(name);
this.account = account;
this.depositAmount = depositAmount;
} @Override
public void run() {
for (int i = 0; i < 100; i++) {
account.deposit(depositAmount);
}
}}
DrawThread.java
public class DrawThread extends Thread {
private Account account;
private double drawAmount; public DrawThread(String name, Account account, double drawAmount) {
super(name);
this.account = account;
this.drawAmount = drawAmount;
} @Override
public void run() {
for(int i=0;i<100;i++) {
account.draw(drawAmount);
}
}
}
测试代码:
DrawTest.java
public class DrawTest {
public static void main(String[] args) {
// 创建一个账户
Account acct = new Account("1234567", 0);
new DrawThread("取钱者甲", acct, 80000).start();
new DrawThread("取钱者乙", acct, 80000).start();
new DrawThread("取钱者丙", acct, 80000).start(); new DepositThread("存钱者张", acct, 80000).start();
new DepositThread("存钱者王", acct, 80000).start();
new DepositThread("存钱者刘", acct, 80000).start();
}}
请大家帮我分析这段代码造成死锁的原因
首先贴代码吧:
Account.java
public class Account {
private String acccountNo;
private double balance;
private volatile boolean flag = false;
private int i = 0; public Account() { } public Account(String accountNo, double balance) {
this.acccountNo = acccountNo;
this.balance = balance;
} public String getAcccountNo() {
return acccountNo;
} public void setAcccountNo(String acccountNo) {
this.acccountNo = acccountNo;
} public double getBalance() {
return this.balance;
} public void draw(double drawAmount) {
synchronized (Account.class) {
if (!flag) {
try {
Account.class.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
System.out.println(Thread.currentThread().getName() + "取钱:" + drawAmount);
balance -= drawAmount;
System.out.println("账户余额为:" + balance);
// 将标识账户是否有存款的旗标设为false
if (balance < 0) {
i++;
System.out.println(
"******************************************************************************************************************************************"
+ i);
flag = false;
Account.class.notifyAll();
}
}
System.out.println(flag);
} } public void deposit(double depositAmount) {
synchronized (Account.class) {
if (flag) {
try {
Account.class.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
System.out.println(Thread.currentThread().getName() + "存款:" + depositAmount);
balance += depositAmount;
System.out.println("账户余额为:" + balance);
if (balance > 0) {
flag = true;
Account.class.notifyAll();
}
}
System.out.println(flag);
}
}
}
DepositThread.java
public class DepositThread extends Thread {
// 模拟用户账户
private Account account;
private double depositAmount; public DepositThread(String name, Account account, double depositAmount) {
super(name);
this.account = account;
this.depositAmount = depositAmount;
} @Override
public void run() {
for (int i = 0; i < 100; i++) {
account.deposit(depositAmount);
}
}}
DrawThread.java
public class DrawThread extends Thread {
private Account account;
private double drawAmount; public DrawThread(String name, Account account, double drawAmount) {
super(name);
this.account = account;
this.drawAmount = drawAmount;
} @Override
public void run() {
for(int i=0;i<100;i++) {
account.draw(drawAmount);
}
}
}
测试代码:
DrawTest.java
public class DrawTest {
public static void main(String[] args) {
// 创建一个账户
Account acct = new Account("1234567", 0);
new DrawThread("取钱者甲", acct, 80000).start();
new DrawThread("取钱者乙", acct, 80000).start();
new DrawThread("取钱者丙", acct, 80000).start(); new DepositThread("存钱者张", acct, 80000).start();
new DepositThread("存钱者王", acct, 80000).start();
new DepositThread("存钱者刘", acct, 80000).start();
}}
请大家帮我分析这段代码造成死锁的原因
public void draw(double drawAmount) {
synchronized (Account.class) {
while (!flag) {
try {
Account.class.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "取钱:" + drawAmount);
balance -= drawAmount;
System.out.println("账户余额为:" + balance);
// 将标识账户是否有存款的旗标设为false
if (balance < 0) {
i++;
System.out.println(
"******************************************************************************************************************************************"
+ i);
flag = false;
Account.class.notifyAll();
} System.out.println(flag);
} }public void deposit(double depositAmount) {
synchronized (Account.class) {
while (flag) {
try {
Account.class.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "存款:" + depositAmount);
balance += depositAmount;
System.out.println("账户余额为:" + balance);
if (balance > 0) {
flag = true;
Account.class.notifyAll();
} System.out.println(flag);
}
}
Account acct = new Account("1234567", 0);
new DrawThread("取钱者甲", acct, 80000).start();
//new DrawThread("取钱者乙", acct, 80000).start();
//new DrawThread("取钱者丙", acct, 80000).start(); new DepositThread("存钱者张", acct, 80000).start();
//new DepositThread("存钱者王", acct, 80000).start();
//new DepositThread("存钱者刘", acct, 80000).start();问题的关键是 notifyAll 方法是随机唤醒一个监听此对象的线程,那么当 draw 线程唤醒了另一个 draw 线程,或者 deposit 线程唤醒了另一个 deposit 线程的时候,此时由于 flag 进入 await 条件一致,那么这个被唤醒的线程将会进入 await 状态(循环了 100 次,所以有机会),这个时候整个程序所有的线程都处于 await