經典的同步問題(銀行取錢)
阿新 • • 發佈:2019-01-10
銀行取錢問題是非常經典的同步問題,如果不採用同步方法,可能也不會發生錯誤,但就是那小概率事件就可以稱之為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
乙餘額不足,取錢失敗
這樣符合”加鎖-修改-釋放鎖“的邏輯,銀行再也不用擔心虧錢了,嘻嘻。