在能同步的地方都已经同步了,为什么还是发生线程污染?

问题这是一段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;//剩余票数等于原来的票数减1
balance.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);
}
}
尚方宝剑之说
浏览 417回答 2
2回答

UYOU

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("支付失败,余额不足");}

慕少森

你同步啥了...synchronized方法锁的是实例对象你4个对象每个对象一把锁自己和自己抢锁谁都能进去哪里同步了
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript