关于多线程的问题

Garvin Li
博客专家认证
2015-03-04 09:45:56
关于抢票问题,一共10张票,三个线程抢,但是为什么出现抢到标号是-1和0的票,详情如下
package multiThread;


class BuyTicket implements Runnable{

private int ticket=10;
// private static int ticket=10;
@Override
public void run() {
// TODO Auto-generated method stub

{
while(ticket>0){
try{

synchronized (this){
System.out.println(Thread.currentThread().getName()+" get the NO."+ticket+"ticket");
ticket--;
}
Thread.sleep(1000);

}
catch(Exception e){
e.printStackTrace();
}
}

}

}
public BuyTicket(){

}
public static void main(String[] args) {
// TODO Auto-generated method stub
BuyTicket a1=new BuyTicket();
new Thread(a1,"小王").start();
new Thread(a1,"小李").start();
new Thread(a1,"小刘").start();
}

}


结果:
小王 get the NO.10ticket
小李 get the NO.9ticket
小刘 get the NO.8ticket
小王 get the NO.7ticket
小刘 get the NO.6ticket
小李 get the NO.5ticket
小李 get the NO.4ticket
小刘 get the NO.3ticket
小王 get the NO.2ticket
小李 get the NO.1ticket
小刘 get the NO.0ticket
小王 get the NO.-1ticket
...全文
142 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
chenjing0320 2015-03-04
  • 打赏
  • 举报
回复
可能存在多个线程进入了while(ticket>0)代码块之内且在synchronized (this)之前的位置,如果这时ticket=1,3个线程也会依次执行ticket--; 改为
synchronized (this) {
					if(ticket > 0) {
						System.out.println(Thread.currentThread().getName() + " get the NO." + ticket + "ticket");
						ticket--;
					}
				}
即可保证ticket>0
Garvin Li 2015-03-04
  • 打赏
  • 举报
回复
自己想到答案了。。 @Override public void run() { // TODO Auto-generated method stub { while(ticket>0){ try{ synchronized (this){ if(ticket>0){ System.out.println(Thread.currentThread().getName()+" get the NO."+ticket+"ticket"); ticket--; } } Thread.sleep(Math.round(Math.random()*1000)); } catch(Exception e){ e.printStackTrace(); } } }
Garvin Li 2015-03-04
  • 打赏
  • 举报
回复
引用 3 楼 jjxiaoxuan 的回复:
@Override public void run() { { while (ticket > 0) { synchronized (this) { if(ticket>0){ try { System.out.println(Thread.currentThread().getName() + " get the NO." + ticket + "ticket"); ticket--; Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); } } } } } } 这样就可以啦..
这样也不对啊,这样一个线程进去就把票都抢了。结果如下: 小王 get the NO.10ticket 小王 get the NO.9ticket 小王 get the NO.8ticket 小王 get the NO.7ticket 小王 get the NO.6ticket 小王 get the NO.5ticket 小王 get the NO.4ticket 小王 get the NO.3ticket 小王 get the NO.2ticket 小王 get the NO.1ticket
flurriedCat 2015-03-04
  • 打赏
  • 举报
回复
做判断的地方加同步锁。 混混分。。
jjxiaoxuan 2015-03-04
  • 打赏
  • 举报
回复
@Override public void run() { { while (ticket > 0) { synchronized (this) { if(ticket>0){ try { System.out.println(Thread.currentThread().getName() + " get the NO." + ticket + "ticket"); ticket--; Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); } } } } } } 这样就可以啦..
Garvin Li 2015-03-04
  • 打赏
  • 举报
回复
引用 1 楼 chenjing0320 的回复:
可能存在多个线程进入了while(ticket>0)代码块之内且在synchronized (this)之前的位置,如果这时ticket=1,3个线程也会依次执行ticket--; 改为
synchronized (this) {
					if(ticket > 0) {
						System.out.println(Thread.currentThread().getName() + " get the NO." + ticket + "ticket");
						ticket--;
					}
				}
即可保证ticket>0
谢谢,回复,但是这样问题还是没解决。结果如下: 小王 get the NO.10ticket 小李 get the NO.9ticket 小刘 get the NO.8ticket 小王 get the NO.7ticket 小李 get the NO.6ticket 小刘 get the NO.5ticket 小李 get the NO.4ticket 小王 get the NO.3ticket 小刘 get the NO.2ticket 小李 get the NO.1ticket 小王 get the NO.0ticket

50,503

社区成员

发帖
与我相关
我的任务
社区描述
Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧