Java面向对象程序设计|模拟银行存取款( 二 )


classAccount{
privateStringname;privateintvalue;//账户余额
publicAccount(Strings,intd){name=s;value=https://pcff.toutiao.jxnews.com.cn/p/20220617/d;}
publicStringgetName(){returnname;}
publicintread(){returnvalue;}//查余额
publicvoidwrite(intx){value=https://pcff.toutiao.jxnews.com.cn/p/20220617/x;}//改余额
}
classATMextendsThread{
privateAccounta;
privateintatmVal;//存/取金额 , 正数/负数表示存入/取出
publicATM(Accounta1,intv){a=a1;atmVal=v;}
publicvoidrun(){//查-改-查
//synchronized(a){//临界区:以原子方式访问临界资源a
StringopStr=(atmVal>0)?"存入"+atmVal+"元":"取出"+(-1*atmVal)+"元";
System.out.print("n"+a.getName+":现有"+a.read+"元 , "+opStr);//查
try{sleep(1);}catch(InterruptedExceptione){;}
a.write(a.read+atmVal);//改
try{sleep(1);}catch(InterruptedExceptione){;}
System.out.print(" , 现有余额"+a.read+"元 。 ");//查
//}//endsynchronized
}
}
classCh_5_5{
publicstaticvoidmain(Stringargs[]){
Accounta=newAccount("张三",100);
ATMatm1=newATM(a,-300);//取钱为负数
ATMatm2=newATM(a,200);//存钱为正数
atm1.start;atm2.start;
}
}
02
输出结果
未使用互斥框架的运行结果
张三:现有100元 , 取出300元
张三:现有100元 , 存入200元 , 现有余额300元 。, 现有余额300元 。
使用互斥框架的运行结果
张三:现有100元 , 取出300元 , 现有余额-200元 。
张三:现有-200元 , 存入200元 , 现有余额0元 。
03
示例剖析
从结果看 , 未使用互斥框架的输出信息杂乱 , 且余额不对 。 使用互斥框架后输出信息完整 , 结果正确的 。 注意:sleep(1)表示休眠1毫秒 。 执行时 , 线程定会放弃处理机 , 故能增加线程间的切换次数 。 本例run中的sleep(1) , 旨在模拟出线程执行的最坏情形:线程间频繁交错 , 这有利于线程的调试 。 由于该方法会产生检查型异常 , 故需要对其进行处理 。 另外 , Thread类还有一个静态方法yield , 又称让步方法 , 能够让线程主动放弃CPU , 将CPU控制权交给相同或更高优先级的线程 。 5.3.4节将介绍 , 由于线程的调度策略 , 线程的优先级效果似乎不明显 , 即yield的效果也不如sleep明显 。
互斥实现机理 。 所有对象上都有一个自动锁 , 初始为开启状态(unlock) , 一旦有线程的临界区访问该对象(即临界资源对象) , 则锁自动锁闭(lock) , 即此线程“持有”锁 。 当临界区执行完毕后 , 则锁自动开启 , 即此线程“释放锁” 。 临界资源锁闭期间 , 任何其他线程无法再访问该临界资源 , 从而可确保线程间以排它方式执行 。 对本例而言 , 首先 , atm1、atm2拥有同一临界资源a(见main方法) , 这是互斥的基础 。 若它们分别关联不同的线程对象 , 就不会产生竞争 。 请读者验证之 。 之后 , 若atm1首先占有a , 则atm2必须等待 , 直至atm1的临界区执行完毕 , atm2才可能获得a的对象锁 , 继而执行 。 若atm2先执行 , 情况类似 。 注意 , 只有对象才有“对象锁” , 换言之 , 基本型没有对象锁 , 不能作为临界资源 。 另外 , 只有临界区执行前才会检查锁的状态 , sleep执行时不会释放锁 。
本例设计的关键点有二:1.在ATM类的run中用synchronized(a){s}框起 , 确保代码段s以原子方式执行;2.main中atm1、atm2关联同一个账户a(即使用同一变量a) , 即确保线程atm1、atm2访问的临界资源是相同的 , 这样二者才能以互斥方式执行 。
实例讲解
Java面向对象程序设计
思想·方法·应用
Java面向对象程序设计|模拟银行存取款