本篇介绍一个经典的线程问题:银行存钱取钱
一个人在银行存钱取钱,要保证的是:取钱的时候,账户必须有钱才能取出来(即账户余额>0),而且在取钱之前要查询余额>0。
存钱的时候必须保证当前存钱的时候,取钱动作是不会产生的,即存钱的金额保证在这个操作中是没有变动的。代码如下:
package com.thread.bank;
public class Bank {
//账户余额
private int sum=0;
/**
* 存钱
* @param money
*/
public synchronized void addMoney(int money) {
sum+=money;
System.out.println(System.currentTimeMillis()+"存进"+money);
}
/**
* 取钱
*/
public synchronized void subMoney(int money)
{
if(sum-money<0)
{
System.out.println("余额不足");
return;
}else {
sum-=money;
System.out.println(System.currentTimeMillis()+"取出"+money);
}
}
/**
* 查询余额
*/
public synchronized void lookMoney()
{
System.out.println("账户余额"+sum);
}
}
银行类,三个方法,存钱,取钱,查询余额。
客户端操作代码如下:
public class TestMain {
public static void main(String args[]){
final Bank bank=new Bank();
Thread tadd=new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub .
while(true){
bank.addMoney(100);
bank.lookMoney();
}
}
},"002");
Thread tsub = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
bank.subMoney(100);
bank.lookMoney();
}
}
},"001");
tsub.start();
tadd.start();
}
}
当001线程中存钱循环一次的时候,持有锁,那么第二次循环的时候必须等第一次循环处理完释放锁之后才能进行操作,
同理到002线程中取钱的时候,后一次循环必须等待前一次循环释放锁之后才能操作,同一时刻,操作sum变量的线程只有一个这样就能保证,在多次操作的时候,保证查询的余额是正确的