问题这是一段Java学习中的例程,四个车站分别抢票。但是无法实现线程安全。需求实现线程安全注释saleT代表车站的类静态类balance代表剩余的票数s1-s4分别代表四个车站我在能用sync修饰的地方都打上了sync,为什么还是无法实现线程安全?↓下面是代码内容packagecom.hssgweb.多线程;//importjava.util.concurrent.locks.ReentrantLock;classbalance{staticdoubleb=1000;publicstaticdoublegetB(){returnb;}publicstaticvoidsetB(doubleb){balance.b=b;}}publicclass铁路12306{publicstaticvoidmain(String[]args){//主方法SaleTs1=newSaleT("1号");SaleTs2=newSaleT("2号");SaleTs3=newSaleT("3号");SaleTs4=newSaleT("4号");Threadth1=newThread(s1);Threadth2=newThread(s2);Threadth3=newThread(s3);Threadth4=newThread(s4);th1.start();th2.start();th3.start();th4.start();}}classSaleTimplementsRunnable{//Locklock=newReentrantLock();StringsaleId;doublebalan;publicSaleT(StringsaleId){super();this.saleId=saleId;}synchronizedvoidpay(){//pay方法balan=balance.getB()-1;//剩余票数等于原来的票数减1balance.setB(balan);/*System.out.println(balan);balan=ti.b.getB();*/}inti=0;//记录一下这玩意儿总共抢了多少张票publicsynchronizedvoidrun(){while(balance.getB()>0){pay();System.out.println("我是"+saleId+"我为自己代言"+"---还剩下"+balance.getB());i++;}System.out.println("我是"+saleId+"我抢了"+i);}}
2 回答
UYOU
TA贡献1878条经验 获得超4个赞
synchronized关键字的底层实现是对象锁,它是作用于某一个对象上的。对于一个以synchronized修饰的方法来说,如果它不是静态方法,那么加锁的对象就是本对象即this;如果它是静态方法,那么加锁的对象是这个类的Class对象(可以用getClass()获得)。在你的代码中,s1、s2、s3和s4是四个不同的对象,因此有四把不同的锁分别控制这四个对象的run()方法,这四个线程同时操作同一个静态变量balance.b,四把锁之间是互不影响的,因此这个代码根本就没有体现任何的线程安全。你应该使用同一把锁控制这四个线程对b的读写过程,或者将b修改为原子类型。//使用同一把锁,最简单的方式是将pay()改为静态方法staticsynchronizeddoublepay(){doubled=Balance.getB();//类名应该大写if(d>=1.0){d-=1.0;Balance.setB(d);returnd;}else{return-1.0;}}publicvoidrun(){doubleb;while((b=pay())>=0){System.out.println(saleId+"支付成功,余额"+b);}System.out.println("支付失败,余额不足");}
添加回答
举报
0/150
提交
取消