银行取钱问题是非常经典的同步问题,如果不采用同步方法,可能也不会发生错误,但就是那小概率事件就可以称之为BUG吧。
没有使用同步方法的代码如下:
public class ErrorTest{
public static void main(String[] args)
{
user ur = new user(1000,"账户");
new errorThread(800,"甲",ur).start();
new errorThread(800,"乙",ur).start();
}
}
class user
{
private int balance;
private String name;
public user(int balance,String name)
{
this.balance = balance;
this.name = name;
}
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
this.balance = balance;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int hashCode()
{
return name.hashCode();
}
@Override
public boolean equals(Object o)
{
if (o == this)
{
return true;
}
if (o.getClass() == user.class && o !=null )
{
user ur = (user)o;
if (ur.name.equals(name))
{
return true;
}
}
return false;
}
}
class errorThread extends Thread
{
private int money;
//private String name;
private user ur;
public errorThread(int money,String name,user ur)
{
super(name);
this.money = money;
this.ur = ur;
}
@Override
public void run()
{
if (ur.getBalance() >= money)
{
System.out.println(getName()+"成功取出钞票"+money);
ur.setBalance(ur.getBalance()-money);
System.out.println("剩下的钱:"+ur.getBalance());
try{
sleep(10);//这里用了sleep(),强制线程切换
}catch(InterruptedException ie)
{
ie.printStackTrace();
}
}
else
{
System.out.println(getName()+"余额不足,取钱失败");
}
}
}
运行你结果如下:
甲成功取出钞票800
乙成功取出钞票800
剩下的钱:200
剩下的钱:-600
这样银行岂不会陪哭了?哈哈哈哈。
因此,必须使用同步方法,通常情况下使用被并发访问的共享资源作为同步监视器,代码如下:
public class ErrorTest{
public static void main(String[] args)
{
user ur = new user(1000,"账户");
new errorThread(800,"甲",ur).start();
new errorThread(800,"乙",ur).start();
}
}
class user
{
private int balance;
private String name;
public user(int balance,String name)
{
this.balance = balance;
this.name = name;
}
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
this.balance = balance;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int hashCode()
{
return name.hashCode();
}
@Override
public boolean equals(Object o)
{
if (o == this)
{
return true;
}
if (o.getClass() == user.class && o !=null )
{
user ur = (user)o;
if (ur.name.equals(name))
{
return true;
}
}
return false;
}
}
class errorThread extends Thread
{
private int money;
//private String name;
private user ur;
public errorThread(int money,String name,user ur)
{
super(name);
this.money = money;
this.ur = ur;
}
@Override
public void run()
{
synchronized(ur)
{
if (ur.getBalance() >= money)
{
System.out.println(getName()+"成功取出钞票"+money);
ur.setBalance(ur.getBalance()-money);
System.out.println("剩下的钱:"+ur.getBalance());
try{
sleep(10);
}catch(InterruptedException ie)
{
ie.printStackTrace();
}
}
else
{
System.out.println(getName()+"余额不足,取钱失败");
}
}
}
}
运行结果如下:
甲成功取出钞票800
剩下的钱:200
乙余额不足,取钱失败
这样符合”加锁-修改-释放锁“的逻辑,银行再也不用担心亏钱了,嘻嘻。